The Event Loop, Visualized

Blocking the loop β€” interactive event loop example

1setTimeout(() => {
2 console.log('am I late?');
3}, 0);
4
5console.log('start spinning');
6
7while (true) {
8 // spinning forever…
9}

A 0ms setTimeout is registered. The callback will be ready in the task queue almost immediately.

1 / 6

Call stack

script

Web APIs β€” browser land

timeout cb 0ms

The event loop β€” is the call stack empty? β†’ drain the microtask queue first β†’ then take one callback.

Microtask queue β€” priority

Callback queue

Console

Fig. β€” Blocking the loop Β· step 1 of 6

What is going on here

Every other example on this site is about ordering. This one is about the thing ordering depends on: the loop only gets a turn when the call stack is empty, and a synchronous loop never lets that happen.

The timer here expires on time and its callback enters the task queue exactly as it should. It simply never gets taken, because taking it requires an empty stack and the while loop is still on it. The queue keeps filling β€” clicks, timers, messages β€” and nothing drains. This is what a frozen tab actually is: not a crash, just a task that will not end.

Rendering is caught in the same trap, since paint happens between loop turns. That is the direct link between long JavaScript and a page that stops scrolling. The remedies all amount to giving the stack a chance to empty: split work into chunks scheduled as separate tasks, yield with await, or move the computation to a Web Worker, which has its own thread and its own loop.

Common questions

Why does a while loop freeze the whole page?

Because it never returns, so the call stack never empties. The event loop cannot select a task, run an event handler or render a frame until the currently running code finishes.

Do timers still fire while JavaScript is blocked?

The timer expires on schedule and its callback is queued, but it cannot run. Once the blocking code finally ends, the overdue callbacks run late and all at once.

How do I run heavy computation without freezing the UI?

Move it to a Web Worker, which runs on its own thread with its own event loop, or split it into chunks scheduled as separate tasks so the browser can render and handle input between them.

Every question on one page β†’Β·Run your own code β†’

Embed this figure in your own post β†’

Drop this into any article or course page. It stays interactive β€” readers can step through it without leaving your site.