Sobes.tech
Middle+

Kāpēc parastie ģeneratori ļauj rakstīt asenhrono kodu?

sobes.tech AI

Atbilde no AI

Parasti JavaScript ģeneratori ļauj rakstīt asynchrone kodu, pateicoties to spējai pārtraukt un atsākt izpildi, kā arī pārsūtīt vērtības abos virzienos (caur yield un next()).

Šeit ir, kā tas darbojas asynhronijas kontekstā:

  1. Izpildes pārtraukšana (yield): Kad tiek sasniegts yield operators, ģenerators tiek pārtraukts un atgriež vērtību. Asinhroniskajā kodā šī vērtība var būt solījums vai cita "darbība", kas jāizpilda asinhroni.

  2. Gaidi asinhrono rezultātu: Ārējais kods (piemēram, "rāvējs" vai ģeneratora ietvars) saņem vērtību, kas nodota caur yield. Ja tā ir solījums, tas gaida tā izpildes vai noraidīšanas pabeigšanu.

  3. Atsāk izpildi (next()): Pēc asinhronas operācijas pabeigšanas (solījuma izpildes), asinhronais rezultāts (solījuma vērtība) tiek atgriezts atpakaļ ģenerators, izmantojot next(). Ģenerators atsāk izpildi no vietas, kur tas bija pārtraukts.

  4. Rezultāta pārsūtīšana: Vērtība, kas nodota ar next(), kļūst par yield izteiksmes rezultātu ģenerators iekšienē. Tādējādi ģenerators var "saņemt" asinhronas operācijas rezultātu un turpināt darbu ar to, it kā kods būtu sinhrons.

Šis modelis rada ilūziju par sinhronu izpildi asinhronām operācijām, padarot kodu lasāmāku un pārvaldāmāku, salīdzinot ar tradicionālo atgriezenisko saiti vai sarežģītām ķēdēm ar .then().

Šāda izmantošana ir piemērs co veida ietvariem (lai gan tagad biežāk ir async/await, kas būtībā ir sintaktiska cukura pārklājuma pār ģeneratoriem un solījumiem):

// Piemērs, kā izmantot ģeneratoru asinhronībai
function* myAsyncGenerator() {
  try {
    const result1 = yield Promise.resolve(1); // Pārtraukšana, solījuma atgriešana
    console.log('Saņemts pirmais rezultāts:', result1); // Atsākšana ar rezultāta nodošanu

    const result2 = yield new Promise(resolve => setTimeout(() => resolve(2), 500)); // Vēl viena asinhrona operācija
    console.log('Saņemts otrais rezultāts:', result2);

    return 'Gatavs'; // ģeneratora pabeigšana
  } catch (error) {
    console.error('Radās kļūda:', error);
  }
}

// Vienkāršs "rāvējs" ģeneratoram (vienkāršots)
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 {
        // Apstrādāt citus vērtību tipus, ja nepieciešams
        handleNext(result.value);
      }
    } else {
      console.log('Ģenerators pabeigts ar rezultātu:', result.value);
    }
  }

  function handleError(error) {
      generator.throw(error);
  }

  handleNext(); // Sākt ģeneratoru
}

// Sākt mūsu asinhrono ģeneratoru
run(myAsyncGenerator);

Šajā piemērā yield Promise.resolve(1) pārtrauc ģeneratoru. "Rāvējs" (vai co) gaida, kamēr solījums tiek izpildīts, un pēc tam atsāk ģeneratoru, nododot vērtību 1 ar next(1). Šī vērtība 1 kļūst par yield Promise.resolve(1) rezultātu ģeneratorā, ļaujot to apstrādāt nākamajā rindā (console.log). Šis mehānisms ļauj imitēt sinhrona izpildes plūsmu asinhronām operācijām.