setTimeout and the Event Loop: Their Relationship in JavaScript
setTimeout callbacks are scheduled by the event loop. Here is how the event loop processes timers.
setTimeout and the Event Loop: Their Relationship in JavaScript
setTimeout and the event loop are deeply connected. Understanding how the event loop processes timer callbacks explains all timer behavior.
The Components
- Call Stack: where JS code runs, one at a time.
- Web APIs: browser-provided APIs like
setTimeout,fetch, DOM events. - Macrotask Queue (Task Queue): callbacks from
setTimeout,setInterval, I/O, UI events. - Microtask Queue: callbacks from
Promise.then,queueMicrotask,MutationObserver. - Event Loop: moves callbacks from queues to the call stack.
How setTimeout Interacts With the Event Loop
- You call
setTimeout(cb, 1000). - The Web API starts a timer for 1000ms.
- The engine continues running synchronous code (it does not wait).
- When the timer fires,
cbis pushed to the macrotask queue. - The event loop checks: is the call stack empty? Are all microtasks done?
- If yes, the event loop moves
cbfrom the macrotask queue to the call stack. cbruns.
Order of Execution
console.log("sync"); setTimeout(() => console.log("timeout"), 0); Promise.resolve().then(() => console.log("promise")); `` **Output**: `sync, promise, timeout`. 1. `sync` runs on the stack. 2. `timeout` callback goes to the macrotask queue. 3. `promise` callback goes to the microtask queue. 4. Stack is empty. The event loop drains the microtask queue: `promise` runs. 5. The event loop takes one macrotask: `timeout` runs. ### Nested `setTimeout` and the Event Loop ```js setTimeout(() => { console.log("first"); setTimeout(() => { console.log("second"); }, 0); }, 0); `` **Output**: `first, second`. The inner `setTimeout` queues its callback. The event loop runs it after the outer callback finishes and microtasks are done. ### Blocking the Stack Delays Timers ```js setTimeout(() => console.log("timer"), 1000); function block() { const start = Date.now(); while (Date.now() - start < 3000) {} // 3 seconds } block(); `` **Output**: `timer` (after 3 seconds). The timer fired at 1 second, but the callback was queued. The event loop could not run it until `block` returned (3 seconds). ### Microtasks Can Delay Macrotasks If a microtask keeps adding more microtasks, the event loop never reaches the macrotask queue: ```js setTimeout(() => console.log("never?"), 0); function infiniteMicrotask() { Promise.resolve().then(infiniteMicrotask); } infiniteMicrotask(); // "never?" is never logged (microtasks starve the macrotask queue) `` ### The Takeaway `setTimeout` callbacks go to the macrotask queue. The event loop runs them only when the call stack is empty and all microtasks are done. This is why `setTimeout(cb, 0)` does not run immediately, why promises run before timers, and why blocking the stack delays timers. Microtasks can starve macrotasks.
setTimeout hands the timer to a Web API. When the timer fires, the callback is pushed to the macrotask queue. The event loop moves it to the call stack only when the stack is empty and all microtasks are done.
Because promise callbacks go to the microtask queue, which the event loop drains completely before taking one task from the macrotask queue where setTimeout callbacks live. Microtasks always run before macrotasks.
Yes. If synchronous code is still running, the callback stays in the macrotask queue. The event loop cannot run it until the stack is empty. A 3-second blocking function delays all queued timers by 3 seconds.
Yes. If a microtask keeps adding more microtasks (like a recursive Promise.then), the event loop never reaches the macrotask queue. The setTimeout callback is never executed. This is called microtask starvation.
Sync code runs first on the call stack. When the stack is empty, the event loop drains all microtasks (promise callbacks, queueMicrotask). Then it takes one macrotask (setTimeout, setInterval, I/O). Then drains microtasks again. This repeats.
Ready to master React completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master React
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

