Explorer
JavaScript

Event loop in js

JavaScript Theory & Concepts

The Event Loop & Concurrency Model

Microtasks, Macrotasks, Call Stack coordination, and browser render cycles.

📖 The Story & Real-World Analogy

The Busy Restaurant and the Diligent Waiter

"Imagine a restaurant with ONE master chef (the Call Stack) cooking dishes one by one. Dishes that take long to bake (a 30-minute pie = `setTimeout` or `fetch`) are handed off to the automated kitchen baking assistants (Browser Web APIs). When dishes finish baking, they are placed in order trays: • The **Microtask Tray** (VIP Promise callbacks): Tiny, urgent garnishes. • The **Macrotask Tray** (Regular Timer & Click callbacks): Full course plates. The Event Loop is the diligent waiter. When the Chef finishes their current dish and their cutting board is empty, the waiter ALWAYS serves ALL VIP Microtasks first! Only when the VIP tray is 100% empty does the waiter serve ONE regular Macrotask dish to the chef, gives the dining room a quick refresh (UI Render), and repeats the loop."

JavaScript is single-threaded: it has one call stack. The Event Loop enables non-blocking asynchronous concurrency by coordinating the execution of code, collecting and processing events, and executing queued sub-tasks.

⚙️ How It Works Under The Hood (Step-by-Step)
1

1. Synchronous Execution in Call Stack

All top-level code and function calls run synchronously on the main thread until the Call Stack is completely empty.

2

2. Web APIs Background Delegation

Async operations (`setTimeout`, DOM events, `fetch`) run on browser background C++ threads, keeping the UI responsive.

3

3. Microtask Queue Processing

Microtasks come from Promises (`.then`, `.catch`, `.finally`), `queueMicrotask()`, and `MutationObserver`. The Event Loop drains the ENTIRE Microtask queue before picking any Macrotask.

4

4. Macrotask (Task) Processing

Macrotasks come from `setTimeout`, `setInterval`, `setImmediate` (Node), and I/O events. The loop picks exactly ONE macrotask per tick.

5

5. Browser Render Pipeline

Between macrotasks, the browser can execute `requestAnimationFrame` and recalculate layout/styles to render frames at 60fps/120fps.

💻 Interactive Code Walkthrough

The ultimate interview execution order puzzle:

JAVASCRIPT
console.log("1. Sync script start");

setTimeout(() => {
  console.log("6. Macrotask: setTimeout 0");
}, 0);

Promise.resolve().then(() => {
  console.log("3. Microtask 1: Promise.then");
  queueMicrotask(() => {
    console.log("4. Microtask 2: nested queueMicrotask");
  });
}).then(() => {
  console.log("5. Microtask 3: Promise chain");
});

console.log("2. Sync script end");
Console Output:
CODE
1. Sync script start
2. Sync script end
3. Microtask 1: Promise.then
4. Microtask 2: nested queueMicrotask
5. Microtask 3: Promise chain
6. Macrotask: setTimeout 0
⚠️ Common Pitfalls & Interview Traps
Trap
Microtask Starvation (UI Freeze)

The Risk: Recursively queueing microtasks (`function starve() { queueMicrotask(starve); }`) continuously refills the microtask queue, completely locking the main thread and preventing DOM rendering or user clicks.

The Fix: Break long-running loops across macrotask ticks using `setTimeout(fn, 0)` or `scheduler.yield()`.

⚡ 30-Second Quick Revision Cheat Sheet (TL;DR)
  • ✓ Execution Order: Synchronous Code → ALL Microtasks → ONE Macrotask → UI Render.
  • ✓ Microtasks: Promises (`then/catch/finally`), `queueMicrotask()`, `MutationObserver`.
  • ✓ Macrotasks: `setTimeout`, `setInterval`, I/O, UI event handlers.
  • ✓ The microtask queue is drained completely to empty on every tick.
  • ✓ Browsers render UI between macrotasks, never in the middle of microtasks.

Finished this lesson?

Mark this chapter complete to update your learning streak and unlock the next lesson.