← Back to libraryQuestion 138 of 468
🟨JavaScriptAdvanced

The Event Loop — Microtasks vs Macrotasks

📌 Definition:

The event loop is the mechanism that lets single-threaded JavaScript perform non-blocking asynchronous work. It continuously moves callbacks from task queues onto the call stack when the stack is empty.

📖 Detailed Explanation:

JavaScript runs on one thread with a call stack. Async callbacks wait in queues: the MACROTASK queue (setTimeout, setInterval, I/O, UI events) and the MICROTASK queue (Promise .then/.catch/.finally, queueMicrotask, async/await continuations). After each macrotask (and after the initial script), the engine drains the ENTIRE microtask queue before rendering or picking up the next macrotask. This means promises always resolve before the next setTimeout, even a setTimeout(fn, 0). Understanding this order explains subtle timing bugs and why a flood of microtasks can starve rendering.

🔑 Key Points:
  • JS is single-threaded; the event loop schedules async callbacks
  • Microtasks (Promises) run before macrotasks (setTimeout)
  • The whole microtask queue drains between each macrotask
  • setTimeout(fn, 0) still runs after all pending microtasks
🌍 Real-World Example:

A flaky UI test fails because an assertion runs before a promise-based state update. Knowing microtasks flush before timers explains why awaiting a microtick (await Promise.resolve()) or the framework's 'flush' helper fixes the ordering, while a setTimeout(0) hack is less reliable.

🎯 Scenario-Based Interview Question:

What is the output order? console.log('A'); setTimeout(() => console.log('B'), 0); Promise.resolve().then(() => console.log('C')); console.log('D');