Sobes.tech
Middle+

Neden sıradan jeneratörler asenkron kod yazmaya izin verir?

sobes.tech yapay zeka

AI'dan gelen yanıt

JavaScript'teki yaygın jeneratörler, duraklatıp yeniden başlatma yetenekleri ve her iki yönde de değer iletebilme kapasiteleri sayesinde asenkron kod yazmaya olanak tanır (yield ve next() aracılığıyla).

İşte bunun asenkronite bağlamında nasıl çalıştığı:

  1. İşlemi durdurma (yield): yield ifadesine ulaşıldığında, jeneratör duraklar ve bir değer döner. Asenkron kodda, bu değer bir promise veya başka bir "eylem" olabilir, ki bu asenkron olarak gerçekleştirilmelidir.

  2. Asenkron sonucu bekleme: Dış kod (örneğin, bir "runner" veya jeneratör için bir sarmalayıcı) yield aracılığıyla geçirilen değeri alır. Eğer bu bir promise ise, onun çözülmesini veya reddedilmesini bekler.

  3. İşlemi devam ettirme (next()): Asenkron işlemin tamamlanmasının ardından (promise çözümlemesi), asenkron sonuç (promise'in değeri) tekrar next() yöntemiyle jeneratöre iletilir. Jeneratör, durakladığı yerden devam eder.

  4. Sonucun iletimi: next() ile iletilen değer, jeneratör içindeki yield ifadesinin sonucu olur. Böylece, jeneratör, asenkron işlemin sonucunu "alabilir" ve onunla çalışmaya devam edebilir, sanki kod senkronmuş gibi.

Bu desen, asenkron işlemler için senkron yürütme izlenimi yaratır, kodu daha okunabilir ve yönetilebilir kılar, geleneksel callback kullanımı veya karmaşık .then() zincirlerine kıyasla.

Bunun bir örneği, co gibi sarmalayıcıların kullanılmasıdır (şu anda async/await daha yaygın olsa da, esasen jeneratörler ve promise'ler üzerinde sözdizimi şekeridir):

// Asenkronluk için jeneratör kullanımı örneği
function* myAsyncGenerator() {
  try {
    const result1 = yield Promise.resolve(1); // Duraklatma, promise döndürür
    console.log('İlk sonuç alındı:', result1); // Sonuç ile devam et

    const result2 = yield new Promise(resolve => setTimeout(() => resolve(2), 500)); // Başka bir asenkron işlem
    console.log('İkinci sonuç alındı:', result2);

    return 'Tamamlandı'; // Jeneratörü sonlandır
  } catch (error) {
    console.error('Bir hata oluştu:', error);
  }
}

// Jeneratör için basit "runner" (sadeleştirilmiş)
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('Jeneratör tamamlandı, sonuç:', result.value);
    }
  }

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

  handleNext(); // Jeneratörü başlat
}

// Asenkron jeneratörümüzü çalıştırıyoruz
run(myAsyncGenerator);

Bu örnekte, yield Promise.resolve(1) jeneratörü duraklatır. "Runner" (veya co) promise çözülene kadar bekler ve sonra next(1) ile jeneratörü devam ettirir. Bu değer 1, jeneratör içindeki yield Promise.resolve(1) ifadesinin sonucu olur ve onu bir sonraki satırda (console.log) işleyebiliriz. Bu mekanizma, asenkron işlemler için senkron akış izlenimi yaratmaya olanak tanır.