2026-11-13 · post
The Zero That Waited — Horn and the JavaScript Event Loop
The Zero That Waited
Late at night, Horn brushed a curl of board foam away from the laptop. The workshop was quiet enough to hear the fan change speed. On the screen, four lines waited for a prediction.
```javascript console.log('start'); setTimeout(() => console.log('timeout'), 0); Promise.resolve().then(() => console.log('promise')); console.log('end'); ```
Horn wrote on the back of a scrap of sandpaper:
```text start end timeout promise ```
The two ordinary logs would run first. That much seemed solid. After that, the timeout had been registered first, and zero looked like a fairly emphatic request.
Horn ran the snippet in the browser console.
```text start end promise timeout ```
No error. Just two lines exchanging places without asking.
Horn kept both lists in view. Rerunning it would be easy; understanding it would take a little longer.
The first mistake was treating everything deferred as one queue.
Calling `setTimeout` registered a timer. Its callback would run as a later task, once the timer allowed it and the event loop could take it up. Zero did not mean now. It certainly did not mean interrupt the script.
The promise was already fulfilled. Calling `.then()` queued its reaction as a microtask—not an ordinary timer task. That reaction still had to wait for the current synchronous code to finish, which was why `end` appeared before `promise`.
Then came the distinction Horn had missed: after the current task finished and the call stack emptied, the browser drained the microtask queue before moving on to another task. The promise callback got its turn before the timeout callback, even though its line came later in the source.
Horn drew three small boxes beneath the wrong prediction:
```text current script → microtasks → next task ```
Under the middle box, a note: any microtasks added here get drained too. Not one callback from each queue in polite rotation.
The workshop fan eased down. Horn crossed out only the last two lines of the prediction and rewrote them in the observed order.
Nothing had jumped the queue. There had been more than one queue all along.
Horn