How does the JavaScript Event Loop coordinate the Call Stack, Microtasks, and Macrotasks?
JavaScript is single-threaded, meaning it has a single call stack that executes one operation at a time. The Event Loop continuously monitors the call stack and task queues to enable non-blocking asynchronous I/O.
Execution order: 1. Synchronous code on the Call Stack runs to completion. 2. When the stack is empty, the Event Loop flushes the entire **Microtask Queue** (Promise callbacks, `queueMicrotask`, `process.nextTick`). 3. The browser performs UI rendering if necessary. 4. The Event Loop picks and executes the oldest task from the **Macrotask Queue** (`setTimeout`, `setInterval`, I/O callbacks). 5. The cycle repeats continuously.
console.log("1: Synchronous start");
setTimeout(() => {
console.log("4: Macrotask (setTimeout)");
}, 0);
Promise.resolve().then(() => {
console.log("3: Microtask (Promise)");
});
console.log("2: Synchronous end");
// Output Order:
// 1: Synchronous start
// 2: Synchronous end
// 3: Microtask (Promise)
// 4: Macrotask (setTimeout)Even though `setTimeout` has a 0ms delay, it is queued as a macrotask. All microtasks (like Promise `.then`) are guaranteed to drain completely before the next macrotask runs.