Asynchronous Event Loop
JavaScript can only execute one piece of code at a time.
JavaScript can only execute one piece of code at a time.
While JavaScript is busy, other JavaScript code must wait.
How do JavaScript handle timers, user clicks, downloads, and asynchronous operations?
The answer is the Event Loop.
Share
Understanding the Event Loop
Understanding the Event Loop explains many common JavaScript behaviors.
- Why setTimeout(..., 0) does not execute immediately.
- Why long loops freeze a page.
- Why Promises execute before timers.
- Why await does not block the browser.
- Why click events wait until current code has finished.
JavaScript Executes One Task at a Time
JavaScript executes code in sequence.
Only one function can execute at any given moment.
Functions execute in the order they are called.
Each function must finish before the next one can begin.
Examples
Example Code
javascriptfunction step1() {
myDisplayer("Step 1");
}
function step2() {
myDisplayer("Step 2");
}
step1();
step2();The Browser Performs Asynchronous Work
JavaScript itself does not wait for timers or download web pages.
Instead, the browser performs these operations while JavaScript continues running.
Examples include:
- Timers
- Network requests
- User events
- File loading
When an operation finishes, JavaScript is notified that the result is ready.
The Event Loop
The Event Loop continuously checks whether JavaScript is busy.
When JavaScript finishes its current task, the Event Loop starts the next waiting task.
This process repeats for as long as the page is open.
Example
Example Code
javascriptJavaScript starts
↓
Run code
↓
Start timer
↓
Continue running
↓
Timer finishes
↓
Event Loop
↓
Run callbackExample: setTimeout()
The callback is not executed immediately.
Instead, it waits until JavaScript finishes its current work.
Example
Example Code
javascriptmyDisplayer("A");
setTimeout(function() {
myDisplayer("B");
}, 2000);
myDisplayer("C");The timer finishes almost immediately.
However, the callback cannot run until JavaScript finishes executing the current code.
The Event Loop starts the callback after the current task has completed.
Example: Promise
Example
Example Code
javascriptmyDisplayer("A");
Promise.resolve().then(function() {
myDisplayer("B");
});
myDisplayer("C");Why did the Promise callback run before the timer?
The answer is that Promise callbacks are placed in a special queue with higher priority.
Task Queue and Microtask Queue
JavaScript uses two main queues for asynchronous work.
| Queue | Contains |
|---|---|
| Task Queue | Timers, events, messages |
| Microtask Queue | Promise handlers and awai |
After each task finishes, JavaScript processes all waiting microtasks before starting the next task.
Comparing Timers and Promises
| Operation | Queue |
|---|---|
| setTimeout() | Task Queue |
| setInterval() | Task Queue |
| Click event | Task Queue |
| Promise.then() | Microtask Queue |
| catch() | Microtask Queue |
| finally() | Microtask Queue |
| await continuation | Microtask Queue |
Long Tasks Block JavaScript
If JavaScript executes a long-running task, everything else must wait.
During this time, the browser cannot execute other JavaScript code.
User clicks, timers, and completed downloads must wait until the current task finishes.
Example
Example Code
javascriptfunction wait() {
let i = 4e9;
while (--i > 0);
}
myDisplayer("Start");
wait();
myDisplayer("Done");Example Explained
Example
Example Code
javascriptmyDisplayer("Start");
wait();
myDisplayer("Done");Step 1
Example Code
javascriptmyDisplayer("Start");Step 2
Example Code
javascriptwait();Step 3
Example Code
javascriptmyDisplayer("Done");Step 4
Example Code
htmlStart DoneThe Timeline
Example Code
javascriptJavaScript starts
↓
myDisplayer("Start")
(DOM changes)
↓
wait()
(JavaScript busy)
↓
myDisplayer("Done")
(DOM changes again)
↓
JavaScript finishes
↓
Browser repaints
↓
Screen shows:
Start DoneWant to show "Start" first?
Example
Example Code
javascriptfunction wait() {
let i = 4e9;
while (--i > 0);
}
myDisplayer("Start");
setTimeout(function () {
wait();
myDisplayer("Done");
}, 0);The Timeline
Example Code
javascriptJavaScript starts
↓
Display "Start"
↓
Current task finishes
↓
Browser repaints
(Start becomes visible)
↓
Event Loop
↓
Run wait()
↓
Display "Done"
↓
Browser repaintsSummary
- JavaScript executes one task at a time.
- The browser performs asynchronous operations such as timers, downloads, and user events.
- Completed operations wait until JavaScript is ready.
- The Event Loop starts waiting tasks when the current task has finished.
- Promise handlers and await continuations run before timers because they use the Microtask Queue.
Interactive Code Examples
Examples
javascriptfunction step1() {
myDisplayer("Step 1");
}
function step2() {
myDisplayer("Step 2");
}
step1();
step2();Example 2
javascriptJavaScript starts
↓
Run code
↓
Start timer
↓
Continue running
↓
Timer finishes
↓
Event Loop
↓
Run callbackJS Example 3
javascriptmyDisplayer("A");
setTimeout(function() {
myDisplayer("B");
}, 2000);
myDisplayer("C");JS Example 4
javascriptmyDisplayer("A");
Promise.resolve().then(function() {
myDisplayer("B");
});
myDisplayer("C");JS Example 5
javascriptfunction wait() {
let i = 4e9;
while (--i > 0);
}
myDisplayer("Start");
wait();
myDisplayer("Done");JS Example 6
javascriptmyDisplayer("Start");
wait();
myDisplayer("Done");