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:
- Call Stack: Executes synchronous code blocks immediately.
- Microtask Queue: Processes items like Promise callbacks,
queueMicrotask, and MutationObserver. This queue is cleared completely before yielding back to rendering. - Macrotask Queue (Task Queue): Processes events,
setTimeout, andsetInterval. 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.