Sobes.tech
Middle+

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:

  1. Täitmise peatamine (yield): Kui jõutakse yield kä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.

  2. Ootamine asünkroonse tulemuse saamiseks: Väliskood (näiteks "jooksja" või generaatori ümbris) saab väärtuse, mis edastatakse yield kaudu. Kui see on promise, ootab see selle täitmist või tagasilükkamist.

  3. Täitmise jätkamine (next()): Pärast asünkroonse operatsiooni (promise täitmise) lõpetamist edastatakse asünkroonne tulemus (promise väärtus) tagasi generaatorile next() meetodi kaudu. Generaator jätkab täitmist sealt, kus see oli peatatud.

  4. Tulemuse edastamine: Välja next() kaudu edastatud väärtus saab olema yield vä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.