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
1// Understanding execution order2console.log("1"); // Synchronous34setTimeout(() => console.log("2"), 0); // Macrotask56Promise.resolve().then(() => console.log("3")); // Microtask78console.log("4"); // Synchronous910// Output: 1, 4, 3, 211// Sync first → Microtasks → Macrotasks1213// More complex example14console.log("Start");1516setTimeout(() => {17 console.log("Timeout 1");18 Promise.resolve().then(() => console.log("Promise inside timeout"));19}, 0);2021Promise.resolve()22 .then(() => {23 console.log("Promise 1");24 return Promise.resolve();25 })26 .then(() => console.log("Promise 2"));2728setTimeout(() => console.log("Timeout 2"), 0);2930console.log("End");3132// Output: Start, End, Promise 1, Promise 2,33// Timeout 1, Promise inside timeout, Timeout 23435// Visualizing the call stack36function 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]4344// queueMicrotask45queueMicrotask(() => console.log("Microtask!"));4647// Stack overflow example48// function infinite() { infinite(); } // RangeError: Maximum call stack size exceeded
🏋️ Practice Exercise
Mini Exercise:
- Predict the output of code mixing console.log, setTimeout, and Promise.then
- Draw the call stack for a series of nested function calls
- Write code demonstrating that microtasks drain completely before macrotasks
- 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 microtasksThinking 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
requestAnimationFrameor Web Workers for heavy computationForgetting that
async/awaitis syntactic sugar over Promises —awaitpauses 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.