Nima uchun oddiy generatorlar asinxron kod yozishga imkon beradi?
sobes.tech AI
AIdan javob
JavaScript-da odati generatorlar yordamida asinxron kod yozish mumkin, chunki ular bajarilishini to'xtatish va davom ettirish imkoniyatiga ega, shuningdek, qiymatlarni ikkala yo'nalishda uzatish (yield va next()) imkonini beradi.
Bu qanday ishlashini asinxronlik kontekstida ko'rib chiqamiz:
-
Bajarishni to'xtatish (
yield):yieldoperatoriga yetib borgach, generator to'xtaydi va qiymatni qaytaradi. Asinxron kodda, bu qiymat promise yoki boshqa "harakat" bo'lishi mumkin, uni asinxron tarzda bajarish kerak. -
Asinxron natijani kutish: Tashqi kod (masalan, "runner" yoki generator uchun qoplama)
yieldorqali uzatilgan qiymatni oladi. Agar bu promise bo'lsa, uning hal bo'lishini yoki rad etilishini kutadi. -
Bajarishni davom ettirish (
next()): Asinxron operatsiya (promise hal bo'lishi) tugagach, asinxron natija (promise qiymati) qayta generatorganext()metodi orqali uzatiladi. Generator to'xtatilgan joydan davom etadi. -
Natijani uzatish:
next()ga uzatilgan qiymat, generator ichidagiyieldifodasining natijasi bo'ladi. Shu tarzda, generator asinxron operatsiyaning natijasini "olishi" va uning bilan ishlashda davom etishi mumkin, kod sinxron bo'lgandek.
Ushbu usul asinxron operatsiyalar uchun sinxron bajarilish illyuziyasini yaratadi, kodni o'qilishi oson va boshqarilishi qulay qiladi, an'anaviy callbacklar yoki murakkab .then() zanjirlari bilan taqqoslaganda.
Buning misoli, co kabi qoplamalar (hozirda async/await ko'proq qo'llaniladi, ular asosan generatorlar va promise'lar ustida sintaktik shakar):
// Asinxronlik uchun generator misoli
function* myAsyncGenerator() {
try {
const result1 = yield Promise.resolve(1); // To'xtatish, promise qaytaradi
console.log('Birinchi natija:', result1); // Qiymat bilan davom etish
const result2 = yield new Promise(resolve => setTimeout(() => resolve(2), 500)); // Yana bir asinxron operatsiya
console.log('Ikkinchi natija:', result2);
return 'Tayyor'; // Generatorni yakunlash
} catch (error) {
console.error('Xato:', error);
}
}
// Generator uchun oddiy "runner" (soddalashtirilgan)
function run(generatorFunc) {
const generator = generatorFunc();
function handleNext(newValue) {
const result = generator.next(newValue);
if (!result.done) {
if (result.value instanceof Promise) {
result.value.then(handleNext).catch(handleError);
} else {
handleNext(result.value);
}
} else {
console.log('Generator yakunlandi:', result.value);
}
}
function handleError(error) {
generator.throw(error);
}
handleNext(); // Generatorni ishga tushirish
}
// Asinxron generatorni ishga tushiramiz
run(myAsyncGenerator);
Bu misolda, yield Promise.resolve(1) generatorni to'xtatadi. "Runner" (yoki co) promise hal bo'lishini kutadi va keyin generatorni next(1) bilan davom ettiradi. Bu qiymat 1 generator ichidagi yield Promise.resolve(1) natijasiga aylanadi va uni keyingi satrda (console.log) ishlashga imkon beradi. Bu mexanizm asinxron operatsiyalar uchun sinxron oqimni imitatsiya qilish imkonini beradi.