Miks tavalised generaatorid võimaldavad kirjutada asünkroonset koodi?
sobes.tech AI
Vastus AI-lt
Tüüpilised JavaScripti generaatorid võimaldavad kirjutada asünkroonset koodi tänu nende võimele peatada ja jätkata täitmist ning edastada väärtusi mõlemas suunas (yield ja next()).
Siin on, kuidas see töötab asünkroonsuse kontekstis:
-
Täitmise peatamine (
yield): Kui jõutakseyieldkäsuni, peatub generaator ja tagastab väärtuse. Asünkroonse koodina võib see väärtus olla promise või muu "tegevus", mis tuleb asünkroonselt täita. -
Ootamine asünkroonse tulemuse saamiseks: Väliskood (näiteks "jooksja" või generaatori ümbris) saab väärtuse, mis edastatakse
yieldkaudu. Kui see on promise, ootab see selle täitmist või tagasilükkamist. -
Täitmise jätkamine (
next()): Pärast asünkroonse operatsiooni (promise täitmise) lõpetamist edastatakse asünkroonne tulemus (promise väärtus) tagasi generaatorilenext()meetodi kaudu. Generaator jätkab täitmist sealt, kus see oli peatatud. -
Tulemuse edastamine: Välja
next()kaudu edastatud väärtus saab olemayieldväljendi tulemus generaatoris. See võimaldab generaatoril "saada" asünkroonse operatsiooni tulemust ja jätkata selle töötlemist, nagu kood oleks sünkroneeritud.
See muster loob illusiooni sünkronsest täitmisest asünkroonsete operatsioonide jaoks, muutes koodi loetavamaks ja hallatavaks võrreldes traditsioonilise callbackide või keerukate .then() ahelate kasutamisega.
Näiteks sellise kasutamise näide on co tüüpi raamistike kasutamine (kuigi nüüd on laiemalt levinud async/await, mis on sisuliselt sünntaksiline suhkur generatoride ja promise'ide üle):
// Näide, kuidas kasutada generaatorit asünkroonsuseks
function* myAsyncGenerator() {
try {
const result1 = yield Promise.resolve(1); // Puhkamine, promise täitmine
console.log('Saadi esimene tulemus:', result1); // Jätkamine tulemuse edastamisega
const result2 = yield new Promise(resolve => setTimeout(() => resolve(2), 500)); // Veel üks asünkroonne operatsioon
console.log('Saadi teine tulemus:', result2);
return 'Valmis'; // Generaatori lõpetamine
} catch (error) {
console.error('Viga:', error);
}
}
// Lihtne "jooksja" generaatorile (lihtsustatud)
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 {
// Muud tüüpi väärtuste töötlemine, kui vaja
handleNext(result.value);
}
} else {
console.log('Generaator lõpetas väärtusega:', result.value);
}
}
function handleError(error) {
generator.throw(error);
}
handleNext(); // Käivitada generaator
}
// Käivitame meie asünkroonse generaatori
run(myAsyncGenerator);
Selles näites peatab yield Promise.resolve(1) generaatori. "Jooksja" (või co) ootab, kuni promise täidetakse, ja seejärel jätkab generaatori, edastades väärtuse 1 next(1) kaudu. See väärtus 1 saab olema yield Promise.resolve(1) tulemus generaatoris, võimaldades seda töödelda järgmisel real (console.log). See mehhanism võimaldab imiteerida sünkrontse täitmise voogu asünkroonsete operatsioonide jaoks.