How JS Handles Everything

JavaScript is single-threaded — it executes one piece of code at a time. So how can it handle network requests, timers, and user clicks without freezing? The answer is the Event Loop and its two task queues.

The Two Queues

Macrotasks (Normal Priority)

  • setTimeout and setInterval callbacks
  • DOM events (click, mousemove, etc.)
  • Network response callbacks
  • Page rendering

Microtasks (High Priority)

  • Promise handlers (.then, .catch, .finally)
  • await continuations
  • queueMicrotask()

The Event Loop Algorithm

  1. Execute the current synchronous code (the first " macrotask " ).
  2. Execute ALL pending microtasks (empty the entire microtask queue).
  3. Render the page if needed.
  4. Execute the next ONE macrotask from the queue.
  5. Repeat from step 2.
console.log('1 - Sync');

setTimeout(() => console.log('3 - Macrotask (setTimeout)'), 0);

Promise.resolve()
  .then(() => console.log('2 - Microtask (Promise)'));

// Output: 1 → 2 → 3
Note

Microtasks have priority. If a promise handler creates ten more promises, the browser won't render or process any macrotask until ALL those microtasks are finished.