← Lessons

quiz vs the machine

Silver1050

Frontend

The Event Loop Microtasks and Macrotasks

JavaScript stays single threaded by draining queues in a strict, predictable order.

4 min read · intro · beat Silver to climb

One thread, many queues

JavaScript runs your code on a single call stack. When the stack empties, the event loop decides what runs next by pulling from queues. Two kinds of work wait there, and they are not treated equally.

  • Macrotasks: timers, message events, and IO callbacks like setTimeout.
  • Microtasks: promise reactions and queueMicrotask callbacks.

The draining rule

After each macrotask, the loop drains the entire microtask queue before rendering or taking the next macrotask. New microtasks scheduled during draining run in the same pass, so a microtask flood can starve the next timer.

  • Synchronous code runs first to completion.
  • Then all pending microtasks run.
  • Then one macrotask, and the cycle repeats.

This is why a promise resolution always fires before a setTimeout of zero, even though both look immediate. Understanding the order removes most surprises about when a callback actually runs.

Key idea

After every macrotask the loop empties all microtasks before doing anything else, so promises always beat timers.

Check yourself

Answer to earn rating on the learn ladder.

1. Which runs first when both are scheduled together?

2. What happens to the microtask queue after a macrotask finishes?