JavaScript Event Loop Interview Questions
One of the most frequently asked JavaScript interview questions is:
How does the JavaScript Event Loop work?
This question appears in:
- Frontend Interviews
- React Interviews
- Senior JavaScript Interviews
- Full Stack Interviews
Interviewers often ask:
- Is JavaScript single-threaded?
- How can JavaScript perform asynchronous operations?
- What is the Event Loop?
- What are Microtasks and Macrotasks?
- Why do Promises execute before
setTimeout?
To answer these questions, we need to understand how JavaScript executes code behind the scenes.
1. Is JavaScript Single-Threaded?
Yes.
JavaScript executes code on a single thread.
This means:
One Task At A TimeExample:
console.log("A");
console.log("B");
console.log("C");Output:
A
B
CJavaScript cannot execute:
A and B simultaneouslyon the same thread.
2. The Problem of Blocking Operations
Consider:
console.log("Start");
setTimeout(() => {
console.log("Timer");
}, 5000);
console.log("End");Output:
Start
End
TimerQuestion:
If JavaScript is single-threaded, why doesn't it wait 5 seconds?
The answer lies in:
Event Loop3. What is the Event Loop?
The Event Loop is a mechanism that allows JavaScript to perform asynchronous operations without blocking the main thread.
It coordinates:
- Call Stack
- Web APIs
- Callback Queue
- Microtask Queue
Together they enable asynchronous behavior.
4. Key Components: Call Stack & Web APIs
The Event Loop relies on four major components:
Call Stack
Web APIs
Callback Queue
Event LoopModern JavaScript also includes:
Microtask QueueCall Stack
The Call Stack keeps track of currently executing functions.
Example:
function greet() {
console.log("Hello");
}
greet();Execution:
Call Stack
greet()
↓
console.log()After execution:
Call Stack EmptyStack Example
function one() {
two();
}
function two() {
three();
}
function three() {
console.log("Done");
}
one();Call Stack:
one()
↓
two()
↓
three()
↓
console.log()Then functions are removed one by one.
Web APIs
Browsers provide APIs outside JavaScript itself.
Examples:
setTimeout
fetch
DOM Events
addEventListener
GeolocationThese APIs are handled by the browser.
Not by the JavaScript engine.
Example
setTimeout(() => {
console.log("Timer");
}, 3000);Execution:
Call Stack
↓
Browser Web API
↓
Wait 3 Seconds
↓
Queue CallbackThe timer does not sit on the Call Stack.
5. Callback Queue (Macrotasks)
After an asynchronous task completes:
setTimeout(...)its callback is placed into the:
Callback QueueExample:
setTimeout(() => {
console.log("Timer");
}, 0);After timer completion:
Callback Queue
console.log("Timer")The callback waits until the Call Stack becomes empty.
Event Loop's Job
The Event Loop continuously checks:
Is Call Stack Empty?If yes:
Move Task From Queue
To Call StackThis process repeats forever.
Visual Representation
Call Stack
↑
|
Event Loop
|
↓
Callback QueueFirst Interview Question
What is the output?
console.log("Start");
setTimeout(() => {
console.log("Timer");
}, 0);
console.log("End");Answer
Output:
Start
End
TimerWhy?
Even:
setTimeout(..., 0)does not execute immediately.
The callback must first enter the queue and wait for the Call Stack to become empty.
6. Promises & the Microtask Queue
Promises do not use the Callback Queue.
They use:
Microtask QueueExample:
Promise.resolve().then(() => {
console.log("Promise");
});Two Important Queues
Microtask Queue
Macrotask QueueExamples:
Microtasks
Promise.then()
catch()
finally()
queueMicrotask()
MutationObserverMacrotasks
setTimeout()
setInterval()
DOM Events
MessageChannel7. Queue Priority: Microtasks vs. Macrotasks
The Event Loop always processes:
Microtasks Firstbefore:
MacrotasksThis is one of the most important interview concepts.
Promise vs setTimeout
What is the output?
console.log("Start");
setTimeout(() => {
console.log("Timer");
}, 0);
Promise.resolve().then(() => {
console.log("Promise");
});
console.log("End");Answer
Output:
Start
End
Promise
TimerWhy?
Execution:
Start
EndThen:
Microtask Queue
↓
PromiseThen:
Macrotask Queue
↓
TimerMicrotasks always run first.
8. Async/Await and the Event Loop
Consider:
async function demo() {
console.log("A");
await Promise.resolve();
console.log("B");
}
demo();
console.log("C");Answer
Output:
A
C
BWhy?
await creates a Promise continuation.
The remaining code:
console.log("B");is placed into the:
Microtask Queue9. Event Loop Execution Order
The Event Loop follows:
1. Execute Sync Code
2. Empty Microtask Queue
3. Execute One Macrotask
4. Empty Microtask Queue Again
5. RepeatThis order is extremely important.
Advanced Interview Question
What is the output?
console.log("1");
setTimeout(() => {
console.log("2");
}, 0);
Promise.resolve().then(() => {
console.log("3");
});
console.log("4");Answer
Output:
1
4
3
2Explanation:
1 → Sync
4 → Sync
3 → Microtask
2 → MacrotaskAdvanced Interview Question
What is the output?
console.log("1");
setTimeout(() => {
console.log("2");
}, 0);
Promise.resolve()
.then(() => {
console.log("3");
return Promise.resolve();
})
.then(() => {
console.log("4");
});
console.log("5");Answer
Output:
1
5
3
4
2Why?
All microtasks finish before any macrotask begins.
10. Browser Rendering and the Event Loop
Browsers typically render:
After Current Task CompletesExample:
button.style.color = "red";
while (true) {}The UI may never update because the thread is blocked.
Why Long Tasks Are Bad
Example:
while (true) {
// Infinite loop
}Result:
Blocked Event LoopEffects:
- Frozen UI
- Delayed timers
- Unresponsive application
11. Common Interview Q&A
Does setTimeout(0) Execute Immediately?
No.
It enters the Macrotask Queue and waits.
Why Do Promises Execute Before Timers?
Because Promise callbacks are Microtasks.
Microtasks have higher priority.
Is JavaScript Multithreaded?
The JavaScript execution thread is single-threaded.
However, browsers provide asynchronous capabilities through Web APIs.
Does Await Block JavaScript?
No.
It pauses only the current async function.
The Event Loop continues running.
What Queue Does Promise.then() Use?
Microtask QueueWhat Queue Does setTimeout() Use?
Macrotask QueueSenior-Level Interview Answer
JavaScript is single-threaded and executes code using a Call Stack. Asynchronous operations such as timers, network requests, and DOM events are handled by browser Web APIs. Once completed, their callbacks are placed into task queues. The Event Loop continuously checks whether the Call Stack is empty and then moves queued tasks onto the stack for execution. Promise callbacks and async/await continuations are scheduled as Microtasks, while setTimeout callbacks are scheduled as Macrotasks. The Event Loop always processes all Microtasks before executing the next Macrotask, which is why Promise callbacks execute before timers.
Common Interview Mistakes
❌ "JavaScript is asynchronous."
Correct:
JavaScript is synchronous and single-threaded.
The Event Loop enables asynchronous behavior.❌ "setTimeout(0) executes immediately."
Correct:
It waits for the Call Stack to become empty.❌ "Promises use the Callback Queue."
Correct:
Promises use the Microtask Queue.❌ "Await blocks JavaScript."
Correct:
Await pauses only the current async function.Event Loop Summary
| Component | Responsibility |
|---|---|
| Call Stack | Executes functions |
| Web APIs | Handle async operations |
| Microtask Queue | Promise callbacks |
| Macrotask Queue | Timers and events |
| Event Loop | Coordinates execution |
Key Takeaways
- Single-Threaded JS: The JS runtime handles one task at a time using a Call Stack, offloading async tasks to Web APIs.
- Microtask Priority: The Microtask Queue (Promises) is completely flushed before the next Macrotask Queue item (timers) executes.
- Event Loop: Monitors the Call Stack and moves callbacks from queues onto the stack once it is empty.
- Browser Rendering: Updates generally occur between event ticks once the stack clears, blocked by long-running loops.