Can someone explain what the JavaScript event loop actually does? I understand it’s responsible for managing the call stack and the task queue, but I’m not clear on how promises, async/await, and callbacks are processed within this loop. How does the engine decide the order of execution for these asynchronous operations? Any visual explanation or simple analogy would help.
Understanding the JavaScript Event Loop and Asynchronous Execution
👁️ 27 görüntüleme💬 2 cevap❤️ 0 beğeni
2 Cevap
The event loop is like a coffee line: the call stack finishes the current brew, then the loop checks the task queue and runs callbacks (macrotasks) while micro‑tasks – promises and the code after `await` – are served immediately after the stack clears. So `await` pauses, the promise resolution lands in the micro‑task queue and jumps ahead of regular callbacks, which wait their turn in the macrotask queue. Sorry if I sound like a confused grandpa, but that’s the order the engine uses! ☕️🤓
Event loop, tek bir thread üzerinde çalışan JavaScript’in “zaman çizelgesi” gibi düşünülebilir. Call‑stack’da senkron kodlar çalışırken, asenkron bir şey (örneğin bir `setTimeout`, bir fetch ya da bir promise) ortaya çıktığında, o iş “bekleme odasına” (task queue ya da micro‑task queue) konur. Loop, stack boşaldığında sırayla bu kuyrukları kontrol eder; önce micro‑task (promise‑then, async/await sonrası) kuyruğunu tüketir, sonra makro‑task (setTimeout, I/O callback) kuyruğuna bakar. Bu yüzden `await` sonrası gelen kod, aynı tick içinde, diğer micro‑task’lerden önce çalışır ama bir sonraki makro‑task’tan önce tamamlanır.
Promise’lar oluşturulduklarında hemen executor fonksiyonu çalışır ve `resolve`/`reject` çağrıldığında callback’leri micro‑task kuyruğuna eklenir. `async` fonksiyon içinde `await` bir promise’i beklediğinde, fonksiyonun geri kalanı da bir micro‑task olarak kuyruğa atılır. Dolayısıyla:
```js
console.log('a');
setTimeout(()=>console.log('b'), 0);
Promise.resolve().then(()=>console.log('c'));
async function foo(){ console.log('d'); await 0; console.log('e'); }
foo();
console.log('f');
```
çıktı `a d f c e b` olur. Burada `setTimeout` makro‑task, `then` ve `await` sonrası kodlar micro‑task, ve bunlar stack boşaldığında sırasıyla işlenir.
Kısacası engine, “stack boş” olduğunda önce micro‑task kuyruğunu (promise‑then, async‑await sonrası) temizler, ardından bir makro‑task alır ve tekrar aynı döngüyü sürdürür. Bu mekanizma, asenkron kodların belirli bir öncelik sırasına göre yürütülmesini sağlar; micro‑task’ler her zaman makro‑task’lerden önce çalışır. Bu yüzden promise zincirleri ve `await` ifadeleri, `setTimeout` gibi klasik callback’lerden “önce” işlenir, ama aynı tick içinde yine asenkron kalır. Valla bu akışı kafada tutmak, event loop diagramı ile bir kez gözden geçirmek işinizi çok kolaylaştırır.