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ığı:
-
İşlemi durdurma (
yield):yieldifadesine 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. -
Asenkron sonucu bekleme: Dış kod (örneğin, bir "runner" veya jeneratör için bir sarmalayıcı)
yieldaracılığıyla geçirilen değeri alır. Eğer bu bir promise ise, onun çözülmesini veya reddedilmesini bekler. -
İşlemi devam ettirme (
next()): Asenkron işlemin tamamlanmasının ardından (promise çözümlemesi), asenkron sonuç (promise'in değeri) tekrarnext()yöntemiyle jeneratöre iletilir. Jeneratör, durakladığı yerden devam eder. -
Sonucun iletimi:
next()ile iletilen değer, jeneratör içindekiyieldifadesinin 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.