The event loop

JavaScript runs on a single thread, but your programs still handle timers, network responses, and DOM events without freezing the page. The event loop is the scheduler that moves work between the call stack, Web APIs, and task queues.

Runtime at a glance

The diagram below is a simplified map of how execution flows: synchronous work fills the call stack, asynchronous work is handled by host APIs, and the event loop decides what runs next.

Interactive runtime map

Step 1 / 8
Call stackEvent loopTask queuesWeb APIstimers · fetch · DOM

Idle: the call stack is empty and task queues have no pending work yet.

Queues & scheduling

When the call stack is empty, the event loop pulls the next task. Two queue families matter in practice:

  • MacrotaskssetTimeout, setInterval, I/O callbacks, UI rendering work.
  • Microtasks — Promises, queueMicrotask, and some internal jobs run before the next macrotask.

That ordering is why promise callbacks can run before the next timer, even if the timer was scheduled first.

Microtasks vs macrotasks

console.log('A')

setTimeout(() => console.log('B'), 0)

Promise.resolve().then(() => console.log('C'))

console.log('D')

The console prints A, D, C, then B. Synchronous code finishes first, microtasks drain next, and the macrotask queue runs after.

Non-blocking I/O

Non-blocking I/O

Network and disk work are delegated to the host. When results arrive, callbacks are queued—your main thread keeps parsing and rendering.

Task prioritization

Microtasks starve macrotasks if enqueued in a loop—always yield for long chains. Browsers may also interleave rendering for responsiveness.

Takeaways

  • The call stack runs synchronous JavaScript; when it empties, the event loop can pick new tasks.
  • Microtasks run to completion before the next macrotask.
  • Timers are not guarantees of exact timing—they schedule macrotasks.

Remember: the loop is cooperative. Long synchronous work still blocks rendering and input—profile hot paths and split work with queueMicrotask, requestAnimationFrame, or chunked scheduling when needed.