Asynchronous JavaScript & The EVENT LOOP โ From Scratch

Table of contents
- Understanding JavaScript in the Browser
- ๐ Web APIs: The Superpowers from the Browser
- ๐ ๏ธ A Simple Asynchronous Code Example
- ๐ Event Loop & Callback Queue Explained
- ๐งฌ Promises & The Microtask Queue
- โ๏ธ Microtask Queue vs Callback Queue
- Common Interview Questions
- 1. What is the Event Loop in JavaScript?
- 2. Whatโs the difference between Microtask Queue and Callback Queue?
- 3. Is console.log() part of JavaScript?
- 4. What happens if setTimeout is set to 0ms?
- 5. Why do event listeners stay in memory after code execution?
- 6. Are synchronous callbacks also handled by the Web API environment?
- โ Final Thoughts
- Best Video to learn this topic :

Note: The Call Stack will execute any execution context that enters it โ no exceptions.
TL;DR: The Call Stack has no timer โ it just runs what's inside it, line by line.
Understanding JavaScript in the Browser
JavaScript, by design, is single-threaded and synchronous. But wait โ if it's synchronous, how does it handle things like network requests, timers, or user interactions without blocking the browser?
Hereโs the secret: JavaScript alone canโt do it all. It relies on the browser environment to handle tasks that would otherwise require multithreading or system-level capabilities.
What Powers the JavaScript Runtime?
When you run JavaScript in the browser, it works hand-in-hand with:
The JavaScript Engine (e.g., V8 in Chrome)
The Call Stack
The Web APIs (provided by the browser)
The Callback Queue
The Microtask Queue
And the Event Loop (the orchestrator)
๐ Web APIs: The Superpowers from the Browser
Web APIs are not part of JavaScript. Theyโre features provided by the browser โ available to JavaScript via the global window
object. Examples include:
setTimeout()
โ scheduling tasksfetch()
โ making HTTP requestsdocument
โ interacting with the DOMconsole.log()
โ printing to the dev consolelocalStorage
โ storing data in the browser
While we often use these without the window.
prefix (like setTimeout()
), behind the scenes they are accessed as window.setTimeout()
.
๐ ๏ธ A Simple Asynchronous Code Example
Letโs take a look at a basic async operation:
console.log("Start");
setTimeout(function cb() {
console.log("Timer expired");
}, 5000);
console.log("End");
What Happens Here?
A Global Execution Context (GEC) is created and pushed to the Call Stack.
console.log("Start")
is executed โ โStartโ is printed.setTimeout(cb, 5000)
is encountered:The
setTimeout
Web API is triggered.The callback
cb()
is registered, and a 5-second timer starts.
console.log("End")
is executed โ โEndโ is printed.After 5 seconds, the timer expires โ but the callback
cb()
cannot go straight to the Call Stack.Instead, it goes to the Callback Queue.
The Event Loop checks if the Call Stack is empty.
Once the Call Stack is clear, it pushes
cb()
into it and executes โ โTimer expiredโ is printed.
๐ Event Loop & Callback Queue Explained
The Event Loop is the invisible mechanism that ensures JavaScript remains non-blocking.
It constantly monitors the Call Stack and Callback Queue.
If the Call Stack is empty and thereโs something in the Callback Queue, it pushes it onto the Call Stack.
This is how asynchronous code is eventually executed.
Why Do We Need a Callback Queue?
Imagine a button clicked six times rapidly:
document.getElementById("btn").addEventListener("click", function cb() {
console.log("Button clicked");
});
Each click triggers the callback cb()
:
These callbacks are stored in the Callback Queue.
The Event Loop pushes them one by one into the Call Stack when it's free.
This queuing mechanism avoids chaos and maintains the execution order.
๐งฌ Promises & The Microtask Queue
Hereโs where it gets interesting. Letโs consider this:
console.log("Start");
setTimeout(function cbT() {
console.log("Timeout callback");
}, 5000);
fetch("https://api.example.com").then(function cbF() {
console.log("Fetch callback");
});
console.log("End");
Step-by-Step Breakdown:
โStartโ is logged.
setTimeout()
registerscbT()
with a 5-second delay.fetch()
initiates a network request and registerscbF()
to be executed once the response arrives (say in 2 seconds).โEndโ is logged.
After 2 seconds,
cbF()
enters the Microtask Queue.After 5 seconds,
cbT()
enters the Callback Queue.The Event Loop gives priority to the Microtask Queue:
It empties the Microtask Queue first โ
cbF()
is executed.Then it processes the Callback Queue โ
cbT()
is executed.
Output:
Start
End
Fetch callback
Timeout callback
โ๏ธ Microtask Queue vs Callback Queue
Feature | Microtask Queue | Callback (Task) Queue |
Priority | High | Lower |
Examples | Promise.then() , MutationObserver | setTimeout() , setInterval() , click handlers |
Execution Timing | After current execution, before next task | After the current task completes |
Risk of Starvation | High (if tasks are recursive) | Low |
Starvation occurs if the Microtask Queue keeps adding new tasks recursively. This can delay or completely block the Callback Queue from being processed.
Common Interview Questions
1. What is the Event Loop in JavaScript?
The Event Loop continuously checks the Call Stack and Callback/Microtask Queues. If the Call Stack is empty, it pushes the next queued task (prioritizing Microtask Queue) onto the Call Stack.
2. Whatโs the difference between Microtask Queue and Callback Queue?
Microtasks (like Promise.then
) are processed before tasks in the Callback Queue (setTimeout
, DOM events). Microtasks have higher priority.
3. Is console.log()
part of JavaScript?
No. Itโs part of the browserโs console
Web API, accessed via the window
object.
4. What happens if setTimeout
is set to 0ms
?
Even with 0ms
, the callback is queued and must wait for the Call Stack to be clear. So, it's never truly "immediate".
5. Why do event listeners stay in memory after code execution?
Event listeners are registered in the Web API environment. They stay alive to respond to events unless manually removed or the page is unloaded. This is why you should remove listeners when theyโre no longer needed to avoid memory leaks.
6. Are synchronous callbacks also handled by the Web API environment?
No. Only asynchronous callbacks (like from setTimeout
, fetch
, etc.) are registered with Web APIs. Synchronous callbacks used with methods like map
, filter
, or reduce
are handled directly by the JavaScript engine.
โ Final Thoughts
JavaScript may be single-threaded, but with the help of the browserโs Web APIs, Callback and Microtask Queues, and the mighty Event Loop โ it becomes incredibly powerful and responsive.
Mastering this internal flow will transform your debugging skills, optimize your performance logic, and give you a major edge in interviews.
Stay curious. Debug deeply. Learn beyond the syntax. ๐
Best Video to learn this topic :
Subscribe to my newsletter
Read articles from UR Prakash Gupta directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

UR Prakash Gupta
UR Prakash Gupta
My name is ๐๐ ๐๐ซ๐๐ค๐๐ฌ๐ก ๐๐ฎ๐ฉ๐ญ๐ and I talk about ๐ง๐ฒ๐ฐ๐ต-๐๐ง๐จ๐ฐ๐ฅ๐๐๐ ๐, ๐ช๐ฒ๐ฏ๐๐ฒ๐, ๐๐ฒ๐๐ข๐ฝ๐ and ๐๐ถ๐ณ๐ฒ๐๐๐๐น๐ฒ.