Ինչու սովորական գեներատորները թույլ են տալիս գրել ասինխրոնային կոդ:
sobes.tech AI
Պատասխան AI-ից
Անհատական գեներատորները JavaScript-ում թույլ են տալիս գրել ասինխրոնային կոդ՝ շնորհիվ նրանց կարողության դադարեցնել և վերականգնել կատարման գործընթացը, ինչպես նաև փոխանցել արժեքներ երկու ուղղություններով (yield և next())։
Ահա թե ինչպես է դա աշխատում ասինխրոնության համատեքստում՝
-
Կատարման դադարեցում (
yield): Երբ հասնում էyieldհրահանգին, գեներատորը դադարեցնում է և վերադարձնում արժեքը։ Ասինխրոնային կոդում, այս արժեքը կարող է լինել մի խոստում (promise) կամ այլ "գործողություն", որը պետք է կատարվի ասինխրոնորեն։ -
Ասինխրոն արդյունքի սպասում: Բաց կոդը (օրինակ, "ռաներ" կամ գեներատորի համար պատվածք) ստանում է
yield-ով փոխանցված արժեքը։ Եթե դա խոստում է, այն սպասում է նրա լուծմանը կամ մերժմանը։ -
Կատարման վերականգնում (
next()): Երբ ասինխրոն գործողությունը (խոստումի լուծումը) ավարտվում է, ասինխրոն արդյունքը (խոստումի արժեքը) փոխանցվում է վերադառնալով գեներատորինnext()մեթոդով։ Գեներատորը շարունակում է կատարմանը այն տեղից, որտեղ դադարեցվել էր։ -
Արդյունքի փոխանցում:
next()-ին փոխանցված արժեքը դառնում էyieldարտահայտության արդյունքը գեներատորի ներսում։ Այսպիսով, գեներատորը կարող է "ստանալ" ասինխրոն գործողության արդյունքը և շարունակել նրա հետ աշխատել, կարծես կոդը սինխրոն լինի։
Այս մոդելը ստեղծում է սինխրոնային կատարման հորինվածություն՝ ասինխրոն գործողությունների համար, ինչը դարձնում է կոդը ավելի ընթեռնելի և կառավարելի՝ համեմատած ավանդական callback-ների կամ բարդ շղթաների .then() օգտագործման հետ։
Օրինակ, այսպիսի օգտագործման օրինակ է co տիպի պատվածքը (համենայն դեպս այժմ ավելի տարածված են async/await, որոնք հիմնականում սինտակսիկ շաքար են գեներատորների և խոստումների վրա).`
// Օրինակ՝ գեներատորի օգտագործում ասինխրոնության համար
function* myAsyncGenerator() {
try {
const result1 = yield Promise.resolve(1); // Դադարեցում, խոստում վերադարձում
console.log('Առաջին արդյունքը ստացանք:', result1); // Վերականգնում արդյունքի փոխանցմամբ
const result2 = yield new Promise(resolve => setTimeout(() => resolve(2), 500)); // Այլ մի ասինխրոն գործողություն
console.log('Երկրորդ արդյունքը ստացանք:', result2);
return 'Պատրաստ է'; // Գեներատորի ավարտ
} catch (error) {
console.error('Սխալ է տեղի ունեցել:', error);
}
}
// Պարզ "ռաներ" գեներատորի համար (պարզեցված)
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('Գեներատորը ավարտվեց արդյունքով:', result.value);
}
}
function handleError(error) {
generator.throw(error);
}
handleNext(); // Գործարկում գեներատորը
}
// Մենք սկսում ենք մեր ասինխրոն գեներատորը
run(myAsyncGenerator);
Այս օրինակով, yield Promise.resolve(1) դադարեցնում է գեներատորը։ "Ռաները" (կամ co) սպասում է, մինչև խոստումը լուծվի, և ապա վերականգնում է գեներատորը, փոխանցելով արժեքը next(1)-ով։ Այս արժեքը 1 դառնում է yield Promise.resolve(1)-ի արդյունքը գեներատորի ներսում, ինչը թույլ է տալիս այն մշակել հաջորդ տողում (console.log)։ Այս մեխանիզմը թույլ է տալիս իմիտացիա ստեղծել սինխրոնային հոսքի համար ասինխրոն գործողությունների։