JavaScript is single-threaded, meaning it executes one block of code at a time. Yet, it manages async behavior flawlessly. Let's explore how the Event Loop coordinates this.

The Execution Order

Asynchronous operations are dispatched and handled in a specific queue order:

  1. Call Stack: Executes synchronous code blocks immediately.
  2. Microtask Queue: Processes items like Promise callbacks, queueMicrotask, and MutationObserver. This queue is cleared completely before yielding back to rendering.
  3. Macrotask Queue (Task Queue): Processes events, setTimeout, and setInterval. The event loop picks one macrotask from this queue at a time.

Code Execution Challenge

Consider the following JavaScript snippet. Try predicting the output sequence:

console.log('Start');

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

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

console.log('End');

Correct Output Sequence:

Start
End
Promise
Timeout

Because the Promise callback enters the Microtask queue, it executes immediately after the synchronous Call Stack empties, before the setTimeout macrotask is processed.

Conclusion

Understanding the Event Loop hierarchy allows you to write performance-optimized scripts and avoid UI blocking during complex calculations.