Facebook Pixel

setTimeout and the Event Loop Relationship Explained

setTimeout callbacks are scheduled by the event loop. Here is how the event loop processes timers.

setTimeout and the Event Loop Relationship Explained

setTimeout and the event loop are deeply connected. Understanding how the event loop processes timer callbacks explains all timer behavior.

How setTimeout Interacts With the Event Loop

  1. You call setTimeout(cb, 1000).
  2. The Web API starts a timer for 1000ms.
  3. The engine continues running synchronous code.
  4. When the timer fires, cb is pushed to the macrotask queue.
  5. The event loop checks: is the call stack empty? Are all microtasks done?
  6. If yes, the event loop moves cb to the call stack. cb runs.

Order of Execution

console.log("sync"); setTimeout(() => console.log("timeout"), 0); Promise.resolve().then(() => console.log("promise"));

Output: sync, promise, timeout.

Blocking the Stack Delays Timers

setTimeout(() => console.log("timer"), 1000); function block() { const start = Date.now(); while (Date.now() - start < 3000) {} } 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.

Microtasks Can Delay Macrotasks

If a microtask keeps adding more microtasks, the event loop never reaches the macrotask queue. The setTimeout callback never runs (microtask starvation).

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.

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.

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, 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. Then it takes one macrotask. 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.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.