Javascript
Mamta Kumawat  

Understanding JavaScript Event Loop with Example (setTimeout vs Promise)?

Meta Description:
Confused why a Promise.then() runs before setTimeout() with a 0ms delay? Learn how JavaScript’s event loop, microtasks, and macrotasks control the execution order, with real code examples.


🔍 Introduction

JavaScript is single-threaded, but thanks to the event loop, it can handle asynchronous operations with surprising precision. One common interview or real-world developer question is:

Why does a Promise.then() run before a setTimeout() with 0ms delay?

Let’s break this down using a simple snippet that’s both deceivingly small and incredibly educational.


🧪 The Code

console.log('1');

setTimeout(() => console.log('2'), 0);

Promise.resolve().then(() => console.log('3'));

console.log('4');

📋 What’s the Expected Output?

Many developers expect this:

1
2
3
4

But the actual output is:

1
4
3
2

Why?


🧠 The JavaScript Execution Model

To understand this, we need to look at:

  • The Call Stack
  • Web APIs (like setTimeout)
  • The Microtask Queue (for Promises)
  • The Macrotask Queue (for setTimeout, setInterval, etc.)
  • The Event Loop, which coordinates everything

🧵 Line-by-Line Breakdown

console.log('1');

This is synchronous. It executes immediately and prints 1.

✅ Output: 1


setTimeout(() => console.log('2'), 0);

  • setTimeout is handled by the browser, not the JavaScript engine.
  • The callback is scheduled in the macrotask queue.
  • The delay is 0ms, but that only means “run as soon as the stack and microtasks are clear.”

⏳ Deferred to: Macrotask Queue


Promise.resolve().then(() => console.log('3'));

  • Promises use the microtask queue.
  • Microtasks always run before macrotasks, even if both are ready at the same time.

✅ Scheduled in: Microtask Queue


console.log('4');

Another synchronous log. It runs immediately.

✅ Output: 4


🔄 Now What Happens?

Once all synchronous code is done, the JavaScript event loop kicks in:

  1. Microtasks (like .then()) are executed first. → Logs 3
  2. Then the first macrotask (like setTimeout) is executed. → Logs 2

🖨 Final Output

1
4
3
2

🧵 Visual Summary of Execution Order

[Call Stack]
1: console.log('1') → prints 1
2: console.log('4') → prints 4

[Microtask Queue]
- Promise.then(...) → prints 3

[Macrotask Queue]
- setTimeout(...) → prints 2

✅ Why Does This Matter?

Understanding JavaScript’s event loop is key to mastering:

  • Asynchronous behavior
  • Performance optimizations
  • Writing predictable, bug-free code

It also clears up one of the most confusing parts of JS: “Why does a Promise run before a setTimeout?”


🧾 TL;DR

CodeTypeExecutes WhenOutput
console.log('1')SynchronousImmediately1
setTimeout(..., 0)MacrotaskAfter microtasks2
Promise.resolve().then(...)MicrotaskAfter sync code3
console.log('4')SynchronousImmediately4

✅ Final Output:

1
4
3
2

✍️ Conclusion

The key takeaway: Microtasks (Promises) are always executed before macrotasks (setTimeout), no matter the delay. Knowing how the event loop, microtask queue, and macrotask queue interact is fundamental to mastering JavaScript asynchronous programming.

Leave A Comment