DEV Community

Satish
Satish

Posted on

Async JavaScript Explained: How setTimeout Really Works

console.log(1);

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

console.log(3);
Enter fullscreen mode Exit fullscreen mode

Output order:

  • First, 1 is printed immediately.
  • Then 3 is printed (because synchronous code runs before the event loop picks up the timeout).
  • Finally, 2 is printed after the current call stack clears, even though the timeout is 0. This demonstrates how JavaScript’s event loop and task queue work.

Execution Flow Diagram
Call Stack (synchronous execution):

  • console.log(1) → prints 1
  • setTimeout(...) → schedules callback (console.log(2)) in the Callback Queue
  • console.log(3) → prints 3 Callback Queue (asynchronous tasks):
  • After the stack is clear, the event loop picks up the scheduled callback:
  • console.log(2) → prints 2

Visual Representation

Call Stack:                 Callback Queue:
-------------------         -------------------
console.log(1)   → 1
setTimeout(...)  → (callback stored here)
console.log(3)   → 3

(Event loop runs → moves callback to stack)

console.log(2)   → 2
Enter fullscreen mode Exit fullscreen mode

This happens because setTimeout(0) doesn’t mean “immediately” — it means “after the current stack finishes.” The event loop ensures synchronous code runs first, then asynchronous callbacks are processed.

Let’s walk through your code execution with a step-by-step timeline using comments so you can visualize exactly how the event loop processes it:

console.log(1); 
// Step 1: Runs immediately → prints "1"

setTimeout(() => {
  console.log(2); 
  // Step 4: Callback is executed after the stack clears → prints "2"
}, 0);
// Step 2: Schedules the callback in the Callback Queue (not executed yet)

console.log(3); 
// Step 3: Runs immediately after step 1 → prints "3"

// Event Loop Timeline:
// --------------------
// 1. Call stack starts → console.log(1) → output: 1
// 2. setTimeout callback registered → placed in Callback Queue
// 3. console.log(3) → output: 3
// 4. Call stack clears → Event Loop moves callback from queue to stack
// 5. console.log(2) → output: 2
Enter fullscreen mode Exit fullscreen mode

Timeline Visualization

[Start]
Call Stack: console.log(1) → Output: 1
Call Stack: setTimeout(...) → Callback stored in Queue
Call Stack: console.log(3) → Output: 3
[Stack Empty]
Event Loop: moves callback → console.log(2) → Output: 2
[End]
Enter fullscreen mode Exit fullscreen mode

This is a classic example of JavaScript’s concurrency model: synchronous tasks first, then asynchronous callbacks once the stack is clear.

Top comments (0)