The Event Loop & Call Stack

📖 Concept

The Event Loop is the mechanism that allows JavaScript to perform non-blocking operations despite being single-threaded.

Call Stack — A LIFO (Last In, First Out) data structure that tracks function execution. JavaScript is single-threaded, meaning only one function runs at a time.

Web APIs — Browser-provided APIs (setTimeout, fetch, DOM events) that handle async operations outside the main thread.

Task Queue (Macrotask) — Holds callbacks from setTimeout, setInterval, I/O operations.

Microtask Queue — Holds callbacks from Promises (.then), queueMicrotask, MutationObserver. Microtasks have higher priority!

Execution order: Call Stack → Microtasks (ALL) → Macrotask (ONE) → Microtasks → Macrotask → ...

🏠 Real-world analogy: The event loop is like a chef (single thread) in a restaurant. They can only cook one dish at a time (call stack), but they put orders in the oven (Web APIs) and check if anything is ready (event loop). Microtasks are like "urgent orders" that cut in line before regular orders (macrotasks).

💻 Code Example

codeTap to expand ⛶
1// Understanding execution order
2console.log("1"); // Synchronous
3
4setTimeout(() => console.log("2"), 0); // Macrotask
5
6Promise.resolve().then(() => console.log("3")); // Microtask
7
8console.log("4"); // Synchronous
9
10// Output: 1, 4, 3, 2
11// Sync first → Microtasks → Macrotasks
12
13// More complex example
14console.log("Start");
15
16setTimeout(() => {
17 console.log("Timeout 1");
18 Promise.resolve().then(() => console.log("Promise inside timeout"));
19}, 0);
20
21Promise.resolve()
22 .then(() => {
23 console.log("Promise 1");
24 return Promise.resolve();
25 })
26 .then(() => console.log("Promise 2"));
27
28setTimeout(() => console.log("Timeout 2"), 0);
29
30console.log("End");
31
32// Output: Start, End, Promise 1, Promise 2,
33// Timeout 1, Promise inside timeout, Timeout 2
34
35// Visualizing the call stack
36function multiply(a, b) { return a * b; }
37function square(n) { return multiply(n, n); }
38function printSquare(n) {
39 const result = square(n); // stack: [printSquare, square, multiply]
40 console.log(result); // stack: [printSquare, console.log]
41}
42printSquare(5); // stack: [printSquare]
43
44// queueMicrotask
45queueMicrotask(() => console.log("Microtask!"));
46
47// Stack overflow example
48// function infinite() { infinite(); } // RangeError: Maximum call stack size exceeded

🏋️ Practice Exercise

Mini Exercise:

  1. Predict the output of code mixing console.log, setTimeout, and Promise.then
  2. Draw the call stack for a series of nested function calls
  3. Write code demonstrating that microtasks drain completely before macrotasks
  4. Create a visualization of the event loop using console logs

⚠️ Common Mistakes

  • setTimeout(fn, 0) doesn't execute immediately — it goes to the macrotask queue AFTER all sync code and microtasks

  • Thinking JavaScript is multi-threaded — it's single-threaded; async operations are handled by the browser/runtime

  • Not knowing microtasks (Promises) execute before macrotasks (setTimeout) — this is a very common interview question

  • Long-running synchronous code blocks the event loop — use requestAnimationFrame or Web Workers for heavy computation

  • Forgetting that async/await is syntactic sugar over Promises — await pauses the function, not the entire thread

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for The Event Loop & Call Stack. Login to unlock this feature.