Event loop in JavaScript runtimes
The event loop is the mechanism in JavaScript that manages how synchronous and asynchronous code runs, since JavaScript can only run one thing at a time.
- JavaScript is single-threaded, with a single call stack.
- Call stack → executes synchronous code.
- Web/Node APIs → hold async operations (timers, fetch, I/O).
- Task queue / Macrotask queue → normal async tasks (setTimeout, events).
- Microtask queue → promises and
process.nextTick
, always executed before the task queue. - Event loop → checks if the call stack is empty, then moves tasks from queues (microtasks first, then tasks).
console.log("1. Start"); // goes to call stack immediately
// TASK QUEUE (macro task)
setTimeout(() => {
console.log("5. From setTimeout (task queue)");
}, 0);
// MICRO TASK QUEUE
Promise.resolve().then(() => {
console.log("3. From Promise (microtask queue)");
});
// MICRO TASK QUEUE (explicit)
queueMicrotask(() => {
console.log("4. From queueMicrotask (microtask queue)");
});
// More synchronous work
console.log("2. End"); // synchronous → runs immediately
Output:
1. Start
2. End
3. From Promise (microtask queue)
4. From queueMicrotask (microtask queue)
5. From setTimeout (task queue/macrotask queue)
Imagine a restaurant with one chef:
- Call stack = the kitchen, cooking the current dish.
- Task queue / Macrotask queue= the line of regular customer orders.
- Microtask queue = the VIP line (promises).
- Event loop = the waiter who feeds orders to the chef when free → VIPs go first.