The Event Loop is the mechanism that allows JavaScript to perform non-blocking asynchronous operations by coordinating the call stack, Web APIs, microtask queue, and macrotask queue.
In short: it decides what runs next in JavaScript.
The Event Loop enables non-blocking behavior in JavaScript by coordinating the call stack, microtask queue, and macrotask queue.
Think: Sync → Microtask (drain all) → Render → Macrotask (one). Promises before timers, always.
The Event Loop is the mechanism that allows JavaScript to perform non-blocking asynchronous operations by coordinating the call stack, Web APIs, microtask queue, and macrotask queue.
In short: it decides what runs next in JavaScript.
| Component | Role |
|---|---|
| Call Stack | Executes synchronous code, one at a time |
| Web APIs | Handle async operations (setTimeout, fetch, DOM events) |
| Microtask Queue | Promise .then/.catch/await callbacks |
| Macrotask Queue | setTimeout, setInterval, DOM events |
| Event Loop | Orchestrates all of the above |
Microtasks always have higher priority than macrotasks.
jsconsole.log("start"); setTimeout(() => console.log("timeout"), 0); Promise.resolve().then(() => console.log("promise")); console.log("end"); // Output: start → end → promise → timeout
Microtasks (higher priority):
Promise.then, Promise.catch, async/awaitqueueMicrotask()MutationObserverMacrotasks (lower priority):
setTimeout, setIntervalsetImmediate (Node.js)Yes. Rendering happens only after:
If microtasks keep scheduling new microtasks → UI freezes.
jsfunction infiniteMicrotask() { Promise.resolve().then(infiniteMicrotask); } infiniteMicrotask(); // Browser hangs — never reaches render!
await pauses the async function and returns control to the caller. Code after await is scheduled as a microtask.
jsasync function foo() { console.log('A'); await Promise.resolve(); console.log('B'); // microtask } console.log('1'); foo(); console.log('2'); // Output: 1 → A → 2 → B
Was this helpful?
4 questions to cement what you just learned.