How does the JavaScript event loop work?

JavaScript Async Advanced 3–5 Yrs5+ Yrs Conceptual 1 min read

Quick Answer

JavaScript runs on a single thread with a call stack. Async work (timers, I/O, promises) is handed to the host, and when it completes a callback is queued. The event loop waits for the stack to empty, then runs all microtasks (promise callbacks, queueMicrotask), then one macrotask (a timer, an event), then repeats — draining microtasks after every macrotask.

JavaScript is single-threaded — there's one call stack. When I call something async like setTimeout or fetch, the host environment handles the waiting, and when it's done it puts a callback on a queue. The event loop's job is: once the call stack is empty, run everything in the microtask queue — that's promise callbacks — then take exactly one task from the macrotask queue, like a timer callback, then drain microtasks again, and repeat. The practical takeaways are that a promise .then always beats a setTimeout(0) queued before it, and that any long synchronous function freezes the whole page because nothing else can run until the stack clears.

Pieces:

  • Call stack — synchronous execution, one frame at a time.
  • Web/Node APIs — setTimeout, fetch, DOM events run outside the engine and schedule callbacks when done.
  • Macrotask (task) queue — timers, I/O, UI events, MessageChannel.
  • Microtask queue — resolved Promise continuations, queueMicrotask, MutationObserver. Higher priority.

Loop iteration: run sync code to completion → drain the entire microtask queue → take one macrotask → drain microtasks again → (render) → repeat.

Why it matters: a promise .then always runs before a setTimeout(…, 0) scheduled earlier. Long synchronous work blocks everything, including rendering — that's why you break up heavy loops or move work to a Web Worker.

JavaScript — ordering
console.log('1');
setTimeout(() => console.log('2 (macrotask)'), 0);
Promise.resolve().then(() => console.log('3 (microtask)'));
console.log('4');

// output: 1, 4, 3 (microtask), 2 (macrotask)