What will be the output? (Promises & Event Loop)
This problem demonstrates the JavaScript event loop execution order: synchronous code → microtasks → macrotasks.
Quick Navigation: Event Loop Execution Order • Why This Order? • Common Pitfalls
Event Loop Execution Order
JavaScript uses an event loop to handle asynchronous operations. The execution order follows this priority:
1. Synchronous code (executes immediately)
2. Microtasks (Promise.then, Promise.catch, queueMicrotask)
3. Macrotasks (setTimeout, setInterval, I/O operations)
Step-by-Step Execution
(async function () {
console.log(1); // 1️⃣ Synchronous - Output: 1
setTimeout(() => console.log(2), 0); // ⏰ Macrotask - Queued
Promise.resolve().then(() => console.log(3)); // 🔵 Microtask - Queued
setTimeout(() => console.log(4), 0); // ⏰ Macrotask - Queued
console.log(5); // 2️⃣ Synchronous - Output: 5
Promise.resolve().then(() => console.log(6)); // 🔵 Microtask - Queued
Promise.reject().catch(() => console.log(7)); // 🔵 Microtask - Queued
console.log(8); // 3️⃣ Synchronous - Output: 8
})();Execution Flow:
1. All synchronous code runs: 1, 5, 8
2. All microtasks execute: 3, 6, 7 (in order they were queued)
3. Macrotasks execute: 2, 4 (in order they were queued)
Final Output:
1
5
8
3
6
7
2
4Why This Order?
Microtasks vs Macrotasks
Microtasks (high priority):
Promise.then()Promise.catch()Promise.finally()queueMicrotask()MutationObserverMacrotasks (lower priority):
setTimeout()setInterval()setImmediate() (Node.js)Key Rules
1. All microtasks complete before any macrotask runs
2. Microtasks are processed until the microtask queue is empty
3. Macrotasks run one at a time, then check for microtasks again
Visual Representation
Call Stack
↓
Synchronous Code (1, 5, 8)
↓
Microtask Queue (3, 6, 7) ← Process ALL
↓
Macrotask Queue (2, 4) ← Process ONE, then check microtasks againCommon Pitfalls
Mistake 1: Thinking setTimeout(0) runs immediately
console.log(1);
setTimeout(() => console.log(2), 0);
console.log(3);
// Output: 1, 3, 2 (not 1, 2, 3!)Even with 0ms delay, setTimeout is a macrotask and waits for all microtasks.
Mistake 2: Not understanding Promise rejection handling
Promise.reject().catch(() => console.log('caught'));
// This IS a microtask and executes immediately.catch() creates a microtask, so it executes before macrotasks.
Mistake 3: Nested Promises
Promise.resolve()
.then(() => {
console.log(1);
return Promise.resolve().then(() => console.log(2));
})
.then(() => console.log(3));
// Output: 1, 2, 3Nested microtasks are added to the queue and processed in order.