Fossils🧠 ConceptualHow Does the JavaScript Event Loop Work?
ðŸĢHatchlingJavaScriptBrowserAsync

How Does the JavaScript Event Loop Work?

The event loop question exposes whether you truly understand asynchronous JavaScript or just memorized callbacks vs promises.

How Does the JavaScript Event Loop Work?

This is a top-tier question because it bridges language mechanics with browser architecture.

The Architecture

JavaScript is single-threaded but non-blocking. The event loop is the mechanism that makes this possible:

┌─────────────┐     ┌──────────────┐
│  Call Stack  │     │  Web APIs    │
│             │     │  (setTimeout,│
│  main()     │────→│   fetch,     │
│  fn()       │     │   DOM events)│
└──────┮──────┘     └──────┮───────┘
       │                    │
       │    ┌───────────────▾──────────┐
       │    │     Callback Queue       │
       │    │  (macrotasks)            │
       │    └───────────────┮──────────┘
       │                    │
       │    ┌───────────────▾──────────┐
       │    │   Microtask Queue        │
       │    │  (Promises, queueMicro)  │
       │    └──────────────────────────┘
       │
  Event Loop: Is call stack empty?
    → Drain ALL microtasks
    → Take ONE macrotask
    → Repeat

The Classic Trick Question

console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');

Output: 1, 4, 3, 2

Why? Synchronous code runs first (1, 4). Then microtasks (Promise → 3). Then macrotasks (setTimeout → 2).

Microtasks vs Macrotasks

MicrotasksMacrotasks
Promise.then/catch/finallysetTimeout / setInterval
queueMicrotask()I/O callbacks
MutationObserverrequestAnimationFrame
process.nextTick (Node)UI rendering

The critical difference: all microtasks drain before the next macrotask. This means Promises always resolve before setTimeout, even with setTimeout(fn, 0).

The Rendering Connection

The browser's rendering pipeline is tied to the event loop:

  1. Run a macrotask
  2. Drain all microtasks
  3. If it's time to render (~16ms for 60fps):
    • Run requestAnimationFrame callbacks
    • Style calculation → Layout → Paint → Composite

This is why requestAnimationFrame is the right tool for animations — it's synchronized with the browser's render cycle.

Senior Signal

Discuss the event loop in terms of:

  1. Why it exists — single-threaded but non-blocking I/O
  2. The queue priority — microtasks always before macrotasks
  3. Real implications — long microtask chains can block rendering
  4. Practical usage — choosing between setTimeout, rAF, and queueMicrotask

Understanding the event loop isn't about memorizing output puzzles — it's about predicting how your async code will actually execute.