What is the event loop in JavaScript?
The event loop lets single-threaded JavaScript handle asynchronous work without blocking. It keeps checking whether the call stack is empty, then runs the next queued task.
Order of execution:
Call stack — all synchronous code runs first.
Microtasks (Promise callbacks, queueMicrotask) — drained completely after each task; higher priority.
Macrotasks (setTimeout, events, I/O) — one runs per loop iteration.
Key rule: every microtask runs before the next macrotask — that's why a Promise callback fires before setTimeout(0).
console.log('1: sync'); // 1. Call stack
setTimeout(() => {
console.log('2: macrotask'); // 5. Macrotask queue
}, 0);
Promise.resolve().then(() => {
console.log('3: microtask'); // 3. Microtask queue (higher priority)
});
Promise.resolve().then(() => {
console.log('4: microtask 2'); // 4. Microtask queue
});
console.log('5: sync'); // 2. Call stack
// Output order:
// 1: sync
// 5: sync
// 3: microtask
// 4: microtask 2
// 2: macrotask
// Practical: microtask can starve macrotasks
function recursiveMicrotask() {
Promise.resolve().then(() => {
console.log('microtask');
recursiveMicrotask(); // Infinite microtasks!
// setTimeout callbacks will NEVER run
});
}Synchronous code runs first (1, 5). Then ALL microtasks drain (3, 4) — Promises have higher priority.
Then one macrotask (2) — setTimeout even with 0ms delay runs after microtasks. The recursive microtask example shows that microtasks can starve macrotasks (setTimeout never fires).
The output order question (sync, microtask, macrotask) is the #1 event loop interview question. Key rule: ALL microtasks drain before the next macrotask.
Promise.then is a microtask, setTimeout is a macrotask. Show you can predict execution order.