If youโve ever wondered โHow does JavaScript handle asynchronous tasks like setTimeout, API calls, or promises while still being single-threaded?โ โ the answer lies in the Event Loop.
Understanding the event loop is one of the most important concepts to master as a JavaScript developer, whether youโre building front-end apps with React/Angular or back-end services with Node.js.
๐งต 1. JavaScript Is Single-Threaded
JavaScript runs in a single thread, meaning it executes one task at a time.
This thread uses the call stack (a stack data structure) to keep track of function execution.
If one task takes too long (like a heavy loop), it can block everything else.
๐ Thatโs where asynchronous programming and the event loop come in.
โ๏ธ 2. Components of the Event Loop
To understand the event loop, you need to know about these four main parts:
Call Stack โ Keeps track of function execution.
Heap โ Memory allocation for objects.
Web APIs (Browser APIs / Node APIs) โ Provide async features like setTimeout, fetch, or fs.readFile.
Task Queues โ Queues that hold callbacks waiting to be executed:
Macro-task Queue: e.g., setTimeout, setInterval, I/O callbacks.
Micro-task Queue: e.g., Promises, process.nextTick (Node.js).
The Event Loop continuously checks:
โก๏ธ If the call stack is empty, it pushes tasks from the queue into the stack.
๐ 3. How the Event Loop Works (Step by Step)
Letโs take an example:
console.log("Start");
setTimeout(() => {
console.log("Timeout Callback");
}, 0);
Promise.resolve().then(() => {
console.log("Promise Callback");
});
console.log("End");
โ
Output:
Start
End
Promise Callback
Timeout Callback
โ Why?
console.log("Start") โ runs immediately.
setTimeout(..., 0) โ goes to Web API, then Macro-task Queue.
Promise.resolve().then(...) โ goes to Micro-task Queue.
console.log("End") โ runs immediately.
Event Loop: Stack is empty โ executes Micro-tasks first โ "Promise Callback".
Finally, executes Macro-tasks โ "Timeout Callback".
๐ Micro-tasks always have higher priority than Macro-tasks.
๐ฐ 4. Visual Representation
Imagine the Event Loop as a traffic controller:
Cars (functions) are waiting to pass through a single-lane bridge (call stack).
The controller (event loop) checks: if the bridge is empty, allow the next car from the priority queue (micro-tasks first, then macro-tasks).
๐ก 5. Real-World Example
Case: API Call Simulation
console.log("Fetching data...");
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then(response => response.json())
.then(data => console.log("Data:", data));
console.log("Other work...");
Output Order:
Fetching data...
Other work...
Data: { userId: 1, id: 1, title: "...", completed: false }
๐ Why? Because fetch() is asynchronous. The response goes into the micro-task queue after completion, so JavaScript can keep executing other work without blocking.
๐ 6. Why Event Loop Matters
โ Non-blocking I/O: Node.js can handle thousands of requests at once.
โ Efficient UI Rendering: Browsers keep the UI smooth while async tasks run.
โ Understanding Bugs: Knowing micro vs. macro tasks helps debug unexpected execution order.
โ๏ธ 7. Key Takeaways
JavaScript is single-threaded, but async tasks make it powerful.
Event Loop is the mechanism that manages execution order.
Micro-tasks (Promises) run before Macro-tasks (setTimeout).
Mastering this concept helps you write efficient, bug-free, and performant code.
๐ Final Thoughts
The event loop is the engine that powers asynchronous JavaScript.
Without it, JavaScript would be limited to simple, blocking tasks. But thanks to the event loop, we get fast web apps, real-time servers, and smooth user experiences.
So the next time your code doesnโt execute in the order you expect, remember:
๐ Check the call stack, micro-task queue, and macro-task queue โ the event loop decides the order.
Top comments (0)