Understanding the Event Loop: The Secret Behind JavaScript Concurrency
How well you know JavaScript Single Threaded Asynchronous activity which handles Event Concurrency well ? Predict the output.
Understanding the Event Loop: The Secret Behind JavaScript Concurrency

Simple JavaScript Runtime Environment
Take a close look at the following JavaScript snippet. What do you think will be logged to the console, and in what order?
console.log('Script Start')
setTimeout(() => {
console.log('setTimeout: A regular order is ready')
}, 0);
Promise.resolve().then(() => {
console.log('Promise: A VIP order is ready!')
});
console.log('Script End')
Did you guess the output to be
Script Start
setTimeout: A regular order is ready
Promise: A VIP order is ready!
Script End
as timeout was 0 milliseconds and promise was making no API or asycn call ? but let me tell you the output is
Script Start
Script End
Promise: A VIP order is ready!
setTimeout: A regular order is ready
Surprised? Understanding why this happens is the key to truly mastering asynchronous JavaScript. The answer lies in a mechanism called the Event Loop :)
JavaScript’s Concurrency Model: The Busy Kitchen
To understand the event loop, imagine JavaScript’s runtime environment as a busy kitchen with a very talented, but single-minded, chef.
- The Call Stack (The Chef): The chef can only do one thing at a time. The list of tasks the chef is currently working on is the Call Stack. It’s a “Last-In, First-Out” structure. When a function is called, it’s added to the top of the stack; when it’s finished, it’s removed.
- Web APIs (The Kitchen Assistants): The chef doesn’t wait for things like an oven to preheat. For tasks that take time (
setTimeout,fetchrequests, DOM events), the chef delegates to kitchen assistants. In the browser, these are the Web APIs. They handle the task in the background. - The Callback Queue (The “Ready” Counter): When a kitchen assistant finishes a task (like a timer dinging), they don’t interrupt the chef. They place the completed work (the “callback function”) on a “ready for plating” counter. This is the Callback Queue, and it works on a “First-In, First-Out” basis.
The Twist: VIP Orders (Microtasks vs. Macrotasks)
Here’s the crucial part. The “ready” counter is actually split into two different lines:
- The Macrotask Queue: This is the standard “ready” counter. It’s for callbacks from
setTimeout,setInterval, and user interactions like clicks. Think of these as regular orders. - The Microtask Queue: This is a special, high-priority VIP line. It’s for the results of Promises (like
.then()or.catch()) andasync/await. These are VIP orders.
The Event Loop is the head waiter who manages the entire workflow. It has one critical rule:
After the chef finishes a task on the Call Stack, the Event Loop will always check the VIP (Microtask) line first. It will process every single task in the Microtask Queue until it’s empty. Only then will it check the regular (Macrotask) line to process just one task.
Solving the Puzzle
Let’s trace our original code using this model:
**console.log('Script Start'): This is synchronous. It goes directly onto the Call Stack** and is executed.Script Startis logged.**setTimeout(...): This is a Web API task. Its callback is handed off to a "kitchen assistant." After 0ms, the assistant places the callback in the Macrotask Queue** (the regular line).**Promise.resolve().then(...): This is a Promise. It resolves immediately, and its.then()callback is placed in the Microtask Queue** (the VIP line).**console.log('Script End'): Another synchronous task. It goes onto the Call Stack** and is executed.Script Endis logged.
At this point, the initial script is done, and the Call Stack is empty. The Event Loop (our head waiter) steps in:
- Checks Microtasks: It first looks at the VIP line. It finds the promise callback! It pushes this to the Call Stack.
Promise: A VIP order is ready!is logged.
6. Checks Microtasks Again: It checks the VIP line again to ensure it’s empty. It is.
- Checks Macrotasks: Now, it checks the regular line. It finds the
setTimeoutcallback. It pushes this to the Call Stack.setTimeout: A regular order is readyis logged
This explains the execution order perfectly. It’s not about which task was started first, but about the priority of their queues.
Test Your Knowledge
Think you’ve got it? The best way to solidify your understanding is to put it to the test.
Predict the output of the following code snippet. It mixes everything we’ve talked about: synchronous tasks, microtasks, and macrotasks, with a nested twist.
console.log('Test Start')
setTimeout(() => {
console.log('Timeout Callback')
Promise.resolve().then(() => {
console.log('Promise inside Timeout')
})
}, 0)
Promise.resolve().then(() => {
console.log('Promise Callback')
setTimeout(() => {
console.log('Timeout inside Promise')
}, 0)
})
console.log('Test End')
Trace the journey of each function through the Call Stack, Web APIs, and the Microtask/Macrotask queues. Don’t just guess!
Drop your predicted output in the comments below! Let’s see who can crack it.
Happy Coding :)
메타데이터
- post_id
- 8db67fe2a90e
- slug
- understanding-the-event-loop-the-secret-behind-javascript-concurrency-8db67fe2a90e
- url
- https://medium.com/@12fahed/understanding-the-event-loop-the-secret-behind-javascript-concurrency-8db67fe2a90e
- canonical_url
- https://medium.com/@12fahed/understanding-the-event-loop-the-secret-behind-javascript-concurrency-8db67fe2a90e
- author_url
- https://medium.com/@12fahed
- status
- ok
- fetched_at
- 2026-06-15 20:49:13