Node.js uses a single-threaded event loop to handle asynchronous operations. This means that all the JavaScript code is executed on a single thread, but the event loop can handle multiple operations concurrently.
The JavaScript code consists of two lines of execution:
- The mainline: This is the JavaScript that runs when Node first runs your program. It runs from start to finish, and when it is finished, it gives up control to the event loop.
- The event loop: This is where all of your callbacks are run.
The following diagram shows a simplified overview of the event loop's order of operations.
┌───────────────────────────┐
┌─>│ timers │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ pending callbacks │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ idle, prepare │
│ └─────────────┬─────────────┘ ┌───────────────┐
│ ┌─────────────┴─────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └─────────────┬─────────────┘ │ data, etc. │
│ ┌─────────────┴─────────────┐ └───────────────┘
│ │ check │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
└──┤ close callbacks │
└───────────────────────────┘
The event loop in Node.js does not have a predefined number of iterations; it continues running indefinitely until there are no more tasks to perform. Each iteration of the event loop is referred to as a tick. The event loop will keep ticking as long as there are pending operations, such as:
- Promises and other microtasks.
- Pending timers (callbacks scheduled with
setTimeoutorsetInterval). - Pending I/O operations (e.g., file system operations, network requests).
- Pending callbacks (e.g., deferred I/O callbacks).
setImmediatecallbacks.- Close callbacks.
Microtasks
All microtasks are placed into a microtask queue, designed specifically for handling them.
The microtask queue is processed and emptied before every phase iteration of the event loop.
Microtasks are executed at specific points in the event loop:
- After executing JavaScript code: When the call stack becomes empty, the event loop checks for and executes any pending microtasks before moving to the next phase.
- After processing each phase of the event loop: Once the current phase of the event loop is completed, before moving to the next phase, the event loop processes all the pending microtasks.
Here are the main types of microtasks:
- Promise Callbacks:
.then(),.catch(), and.finally()handlers. queueMicrotask: Both queueMicrotask and Promise Callbacks added to the microtask queue and have similar priority.process.nextTick: Callbacks scheduled withprocess.nextTickare executed before promise callbacks or queueMicrotask callbacks.process.nextTickcallbacks are added to the beginning of the microtask queue.
Here's an example:
console.log('Start');
process.nextTick(console.log, "nextTick 1");
Promise.resolve("Promise 1").then(console.log);
queueMicrotask(() => console.log("queueMicrotask 1"));
Promise.reject("Promise 2").catch(console.log);
queueMicrotask(() => console.log("queueMicrotask 2"));
process.nextTick(console.log, "nextTick 2");
console.log('End');
The output would be:
Start
End
nextTick 1
nextTick 2
Promise 1
queueMicrotask 1
Promise 2
queueMicrotask 2
The execution flow is as follows:
- The mainline
- The main thread starts by creating the global execution context and pushes it onto the call stack.
- The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"Start"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread executes
process.nextTickfunction call, a function execution context forprocess.nextTickis added to the call stack. - The main thread moves the
process.nextTickcallback function to the next tick queue. - The main thread removes the function execution context for
process.nextTickfrom the call stack. - The main thread executes Promise constructor call, and its execution context is created and pushed onto the call stack.
- The executor function within the Promise constructor initializes the promise.
- The main thread executes executor function call, and its execution context is created and pushed onto the call stack.
- The main thread executes resolve function call, and its execution context is created and pushed onto the call stack.
- Calling resolve transitions the promise from the pending state to the fulfilled (or resolved) state.
- The value "Promise 1" is set as the value of the new promise internally.
- The main thread removes function execution context for
resolvefrom the call stack. - The main thread removes function execution context for
executor functionfrom the call stack. - The Promise constructor completes, and its execution context is popped off the call stack.
- The main thread executes
.then()method call, and its execution context is created and pushed onto the call stack. - The main thread moves the resolve callback function to the microtask queue (or job queue).
- The main thread removes the execution context for
then()from the call stack. - The main thread executes
queueMicrotaskfunction call, a function execution context forqueueMicrotaskis added to the call stack. - The main thread moves the
queueMicrotaskcallback function to the microtask queue. - The main thread removes the function execution context for
queueMicrotaskfrom the call stack. - The main thread executes the second Promise constructor call, and its execution context is created and pushed onto the call stack.
- The executor function within the second Promise constructor initializes the promise.
- The main thread executes executor function call, and its execution context is created and pushed onto the call stack.
- The main thread executes reject function call, and its execution context is created and pushed onto the call stack.
- Calling resolve transitions the promise from the pending state to the rejected state.
- The value "Promise 2" is set as the value of the new promise internally.
- The main thread removes function execution context for
rejectfrom the call stack. - The main thread removes function execution context for
executor functionfrom the call stack. - The second Promise constructor completes, and its execution context is popped off the call stack.
- The main thread executes
.then()method call, and its execution context is created and pushed onto the call stack. - The main thread moves the resolve callback function to the microtask queue (or job queue).
- The main thread removes the execution context for
then()from the call stack. - The main thread executes the second
queueMicrotaskfunction call, a function execution context for the secondqueueMicrotaskis added to the call stack. - The main thread moves the second
queueMicrotaskcallback function to the microtask queue. - The main thread removes the function execution context for the second
queueMicrotaskfrom the call stack. - The main thread executes the second
process.nextTickfunction call, a function execution context for the secondprocess.nextTickis added to the call stack. - The main thread moves the second
process.nextTickcallback function to the next tick queue. - The main thread removes the function execution context for the second
process.nextTickfrom the call stack. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"End"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - Once all the synchronous code has executed, the main thread removes the global execution context from the call stack.
- The call stack is now empty, waiting for asynchronous callbacks to be executed.
- The event loop starts processing the asynchronous callbacks that have been registered.
- The first loop
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for the first
process.nextTickcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"nextTick 1"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread removes the function execution context for the first
process.nextTickcallback function from the call stack. - The event loop pushes the second task from the nextTick queue onto the call stack and creates a new function execution context for the second
process.nextTickcallback function. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"nextTick 2"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread removes the function execution context for the second
process.nextTickcallback function from the call stack. - The event loop pushes the task from the microtask queue onto the call stack and creates a new function execution context for promise
then()callback function. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"Promise 1"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread removes the function execution context for promise
then()callback function from the call stack. - The event loop pushes the next task from the microtask queue onto the call stack and creates a new function execution context for
queueMicrotaskcallback function. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"queueMicrotask 1"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread removes the function execution context for
queueMicrotaskcallback function from the call stack. - The event loop pushes the next task from the microtask queue onto the call stack and creates a new function execution context for promise
then()callback function. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"Promise 2"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread removes the function execution context for promise
then()callback function from the call stack. - The event loop pushes the next task from the microtask queue onto the call stack and creates a new function execution context for the second
queueMicrotaskcallback function. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"queueMicrotask 2"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread removes the function execution context for the second
queueMicrotaskcallback function from the call stack.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for the first
- Timers Phase
- No timers have expired yet (since less than 500 milliseconds have passed).
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Pending Callbacks Phase
- No pending callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Poll Phase
- No I/O events to process.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
Timers
The first phase of the event loop is the Timers phase. This phase deals with timer callbacks that have reached their scheduled time. Timers in Node.js can be used to schedule code execution after a specified delay or at specific intervals. When a timer's time comes, its callback function is added to the event queue (task queue) to be executed.
Timers are not guaranteed to execute exactly at their scheduled time, as they are subject to the availability of the system and the event loop. For example, if the event loop is busy processing other events, the timer callback may be delayed until the next iteration of the event loop. Therefore, timers should not be used for precise timing, but rather for approximate timing.
Here's an example:
console.log('Start');
setTimeout(() => {
console.log('Timeout callback 1');
}, 1000);
setTimeout(() => {
console.log('Timeout callback 2');
}, 500);
process.nextTick(console.log, "nextTick callback");
queueMicrotask(() => console.log("queueMicrotask callback"));
console.log('End');
The output would be:
Start
End
nextTick callback
queueMicrotask callback
Timeout callback 2
Timeout callback 1
The execution flow is as follows:
- The mainline
- The main thread starts by creating the global execution context and pushes it onto the call stack.
- The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"Start"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread executes
setTimeoutfunction call, a function execution context forsetTimeoutis added to the call stack. - The main thread adds the
setTimeoutcallback function to the timer queue. - The event loop continuously checks the timer queue. When the specified delay has elapsed, the callback function is moved to the appropriate phase of the event loop.
- The main thread removes the function execution context for
setTimeoutfrom the call stack. - The main thread executes the second
setTimeoutfunction call, a function execution context for the secondsetTimeoutis added to the call stack. - The main thread adds the second
setTimeoutcallback function to the timer queue. - The event loop continuously checks the timer queue. When the specified delay has elapsed, the callback function is moved to the appropriate phase of the event loop.
- The main thread removes the function execution context for the second
setTimeoutfrom the call stack. - The main thread executes
process.nextTickfunction call, a function execution context forprocess.nextTickis added to the call stack. - The main thread moves the
process.nextTickcallback function to the next tick queue. - The main thread removes the function execution context for
process.nextTickfrom the call stack. - The main thread executes
queueMicrotaskfunction call, a function execution context forqueueMicrotaskis added to the call stack. - The main thread moves the
queueMicrotaskcallback function to the microtask queue. - The main thread removes the function execution context for
queueMicrotaskfrom the call stack. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"End"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - Once all the synchronous code has executed, the main thread removes the global execution context from the call stack.
- The call stack is now empty, waiting for asynchronous callbacks to be executed.
- The event loop starts processing the asynchronous callbacks that have been registered.
- The first loop
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for
process.nextTickcallback function. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"nextTick callback"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread removes the function execution context for
process.nextTickcallback function from the call stack. - The event loop pushes the task from the microtask queue onto the call stack and creates a new function execution context for
queueMicrotaskcallback function. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"queueMicrotask callback"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread removes the function execution context for
queueMicrotaskcallback function from the call stack.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for
- Timers Phase
- No timers have expired yet (since less than 500 milliseconds have passed).
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Pending Callbacks Phase
- No pending callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Poll Phase
- No I/O events to process.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
- The event loop will continue to loop.
- The next loop
- The first loop starts by running the microtasks queue.
- No microtasks to execute.
- Timers Phase (After 500 milliseconds)
- The event loop pushes the task from the callback queue onto the call stack and creates a new function execution context for the second
setTimeoutcallback function. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"Timeout callback 2"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread removes the function execution context for
setTimeoutcallback function from the call stack. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The event loop pushes the task from the callback queue onto the call stack and creates a new function execution context for the second
- Pending Callbacks Phase
- No pending callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Poll Phase
- No I/O events to process.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue.
- The event loop will continue to loop.
- The next loop
- The first loop starts by running the microtasks queue.
- No microtasks to execute.
- Timers Phase (After 1000 milliseconds)
- The event loop pushes the task from the callback queue onto the call stack and creates a new function execution context for the first
setTimeoutcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Timeout callback 1"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The event loop removes the function execution context for
setTimeoutcallback function from the call stack. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The event loop pushes the task from the callback queue onto the call stack and creates a new function execution context for the first
- Pending Callbacks Phase
- No pending callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Poll Phase
- No I/O events to process.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue.
Pending Callbacks
I/O operations execute in the poll phase of the event loop. During the poll phase, some specific I/O operations callbacks defer to the pending phase of the next iteration of the event loop. I/O operations callbacks deferred from the previous iteration run in the pending callbacks phase.
Here's an example:
console.log('Start');
const fs = require("fs");
fs.readFile(__filename, (err, data) => {
if (err) throw err;
console.log("Pending callback");
});
setTimeout(() => {
console.log('Timeout callback');
}, 0);
process.nextTick(console.log, "nextTick callback");
queueMicrotask(() => console.log("queueMicrotask callback"));
console.log('End');
The output would be:
Start
End
nextTick callback
queueMicrotask callback
Timeout callback
Pending callback
The execution flow is as follows:
- The mainline
- The main thread starts by creating the global execution context and pushes it onto the call stack.
- The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"Start"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread executes
requirefunction call, a function execution context forrequireis added to the call stack. - The main thread starts resolving the module identifier
fs. - The main thread wraps the contents of
fsin a function and executes it, a function execution context forfsis added to the call stack. - The
module.exportsobject is returned and assigned tofs. - The main thread removes function execution context for
fsfrom the call stack. - The main thread removes function execution context for
requirefrom the call stack. - The main thread executes
fs.readFilefunction call, a function execution context forfs.readFileis added to the call stack. - The main thread initiates a non-blocking file system operation to read the current file.
- The main thread removes the function execution context for the first
fs.readFilefrom the call stack. - The main thread executes
setTimeoutfunction call, a function execution context forsetTimeoutis added to the call stack. - The main thread adds the
setTimeoutcallback function to the timer queue. - The event loop continuously checks the timer queue. When the specified delay has elapsed, the callback function is moved to the appropriate phase of the event loop.
- The main thread removes the function execution context for
setTimeoutfrom the call stack. - The main thread executes
process.nextTickfunction call, a function execution context forprocess.nextTickis added to the call stack. - The main thread moves the
process.nextTickcallback function to the next tick queue. - The main thread removes the function execution context for
process.nextTickfrom the call stack. - The main thread executes
queueMicrotaskfunction call, a function execution context forqueueMicrotaskis added to the call stack. - The main thread moves the
queueMicrotaskcallback function to the microtask queue. - The main thread removes the function execution context for
queueMicrotaskfrom the call stack. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"End"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - Once all the synchronous code has executed, the main thread removes the global execution context from the call stack.
- The call stack is now empty, waiting for asynchronous callbacks to be executed.
- The event loop starts processing the asynchronous callbacks that have been registered.
- The first loop
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for
process.nextTickcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"nextTick callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The event loop removes the function execution context for
process.nextTickcallback function from the call stack. - The event loop pushes the task from the microtask queue onto the call stack and creates a new function execution context for
queueMicrotaskcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"queueMicrotask callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The event loop removes the function execution context for
queueMicrotaskcallback function from the call stack.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for
- Timers Phase
- The event loop pushes the task from the timer queue onto the call stack and creates a new function execution context for
setTimeoutcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Timeout callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The event loop removes the function execution context for
setTimeoutcallback function from the call stack. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The event loop pushes the task from the timer queue onto the call stack and creates a new function execution context for
- Pending Callbacks Phase
- The file reading process is finished, but its callback is not yet marked to be executed because IO callbacks get queued up only at the IO Poll Phase.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Poll Phase
- The
fs.readFilecallback event is collected and added to the I/O queue. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
- The event loop will continue to loop.
- The next loop
- The first loop starts by running the microtasks queue.
- No microtasks to execute.
- Timers Phase
- No timeout callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Pending Callbacks Phase
- The event loop pushes the task from the I/O queue onto the call stack and creates a new function execution context for
fs.readFilecallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Pending callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The event loop removes the function execution context for
fs.readFilecallback function from the call stack. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The event loop pushes the task from the I/O queue onto the call stack and creates a new function execution context for
- Poll Phase
- No I/O events to process.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue.
Idle Phase
The idle phase is not a normal phase of the Node.js event loop. It is a period whereby the event loop has nothing to do but perform background tasks like checking for low-priority results or running garbage collection.
Poll Phase
The poll phase is where I/O operations execute. I/O operations transfer data to or from a computer. The event loop checks for new I/O operations and executes them in the poll queue.
Here's an example:
console.log('Start');
const fs = require("fs");
fs.readFile(__filename, (err, data) => {
if (err) throw err;
console.log("Pending callback");
});
const http = require("http");
http.get("http://localhost", (res) => {
console.log("Poll callback");
res.on("data", (chunk) => {
// Do something with the data
console.log("Data event listener callback");
});
});
setTimeout(() => {
console.log('Timeout callback');
}, 0);
process.nextTick(console.log, "nextTick callback");
queueMicrotask(() => console.log("queueMicrotask callback"));
console.log('End');
The output would be:
Start
End
nextTick callback
queueMicrotask callback
Timeout callback
Poll callback
Data event listener callback
Pending callback
The execution flow is as follows:
- The mainline
- The main thread starts by creating the global execution context and pushes it onto the call stack.
- The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"Start"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread executes
requirefunction call, a function execution context forrequireis added to the call stack. - The main thread starts resolving the module identifier
fs. - The main thread wraps the contents of
fsin a function and executes it, a function execution context forfsis added to the call stack. - The
module.exportsobject is returned and assigned tofs. - The main thread removes function execution context for
fsfrom the call stack. - The main thread removes function execution context for
requirefrom the call stack. - The main thread executes
fs.readFilefunction call, a function execution context forfs.readFileis added to the call stack. - The main thread initiates a non-blocking file system operation to read the current file.
- The main thread moves the
fs.readFilecallback function to the I/O queue. - The main thread removes the function execution context for the first
fs.readFilefrom the call stack. - The main thread executes
requirefunction call, a function execution context forrequireis added to the call stack. - The main thread starts resolving the module identifier
http. - The main thread wraps the contents of
httpin a function and executes it, a function execution context forhttpis added to the call stack. - The
module.exportsobject is returned and assigned tohttp. - The main thread removes function execution context for
httpfrom the call stack. - The main thread removes function execution context for
requirefrom the call stack. - The main thread executes
http.getfunction call, a function execution context forhttp.getis added to the call stack. - The main thread initiates initiates an HTTP GET request.
- The main thread moves the
http.getcallback function to the I/O queue. - The main thread removes the function execution context for the first
http.getfrom the call stack. - The main thread executes
setTimeoutfunction call, a function execution context forsetTimeoutis added to the call stack. - The main thread adds the
setTimeoutcallback function to the timer queue. - The event loop continuously checks the timer queue. When the specified delay has elapsed, the callback function is moved to the appropriate phase of the event loop.
- The main thread removes the function execution context for
setTimeoutfrom the call stack. - The main thread executes
process.nextTickfunction call, a function execution context forprocess.nextTickis added to the call stack. - The main thread moves the
process.nextTickcallback function to the next tick queue. - The main thread removes the function execution context for
process.nextTickfrom the call stack. - The main thread executes
queueMicrotaskfunction call, a function execution context forqueueMicrotaskis added to the call stack. - The main thread moves the
queueMicrotaskcallback function to the microtask queue. - The main thread removes the function execution context for
queueMicrotaskfrom the call stack. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"End"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - Once all the synchronous code has executed, the main thread removes the global execution context from the call stack.
- The call stack is now empty, waiting for asynchronous callbacks to be executed.
- The event loop starts processing the asynchronous callbacks that have been registered.
- The first loop
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for
process.nextTickcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"nextTick callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The event loop removes the function execution context for
process.nextTickcallback function from the call stack. - The event loop pushes the task from the microtask queue onto the call stack and creates a new function execution context for
queueMicrotaskcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"queueMicrotask callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes the function execution context for
queueMicrotaskcallback function from the call stack.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for
- Timers Phase
- The event loop pushes the task from the timer queue onto the call stack and creates a new function execution context for
setTimeoutcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Timeout callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes the function execution context for
setTimeoutcallback function from the call stack. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The event loop pushes the task from the timer queue onto the call stack and creates a new function execution context for
- Pending Callbacks Phase
- No pending callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Poll Phase
- The file reading process isn't finished.
- The HTTP request is sent over the network and waits for the server response.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
- The event loop will continue to loop.
- The next loop
- The first loop starts by running the microtasks queue.
- No microtasks to execute.
- Timers Phase
- No timeout callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Pending Callbacks Phase
- The file reading process is finished, but its callback is not yet marked to be executed because IO callbacks get queued up only at the IO Poll Phase.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Poll Phase
- The
fs.readFilecallback event is collected and added to the I/O queue. - When the response headers from the server are received, the event loop pushes the task from the I/O queue onto the call stack and creates a new function execution context for
http.getcallback function. - The server
localhostresponds HTTP GET request, the data starts arriving in chunks. - The event loop executes the data event listener call, a function execution context for data event listener is added to the call stack.
- The event loop moves the calbback function for data event listener to the event queue (task queue).
- Each chunk of data triggers a data event on the response object.
- Once the event loop detects the data event, the event loop will move the callback function for data event listener from the event queue (task queue) to the call stack to be executed and create a new function execution context for callback function.
- The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Data event listener callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes function execution context for callback function from the call stack.
- The data event listener also has no more code to run.
- The event loop removes function execution context for data event listener from the call stack.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue.
- The event loop will continue to loop.
- The next loop
- The first loop starts by running the microtasks queue.
- No microtasks to execute.
- Timers Phase
- No timeout callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Pending Callbacks Phase
- The event loop pushes the task from the I/O queue onto the call stack and creates a new function execution context for
fs.readFilecallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Pending callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes the function execution context for
fs.readFilecallback function from the call stack. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The event loop pushes the task from the I/O queue onto the call stack and creates a new function execution context for
- Poll Phase
- No I/O events to process.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue.
Check Phase
The check phase is where the setImmediate timer runs. The Node.js event loop goes to the check phase when there is a setImmediate in the program, and the poll phase becomes idle or when the poll phase completes.
Here's an example:
console.log('Start');
const fs = require("fs");
fs.readFile(__filename, (err, data) => {
if (err) throw err;
console.log("Pending callback");
});
const http = require("http");
http.get("http://localhost", (res) => {
console.log("Poll callback");
res.on("data", (chunk) => {
// Do something with the data
console.log("Data event listener callback");
});
});
setTimeout(() => {
console.log('Timeout callback');
}, 0);
setImmediate(() => {
console.log("Check callback");
});
process.nextTick(console.log, "nextTick callback");
queueMicrotask(() => console.log("queueMicrotask callback"));
console.log('End');
The output would be:
Start
End
nextTick callback
queueMicrotask callback
Timeout callback
Check callback
Poll callback
Data event listener callback
Pending callback
The execution flow is as follows:
- The mainline
- The main thread starts by creating the global execution context and pushes it onto the call stack.
- The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"Start"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread executes
requirefunction call, a function execution context forrequireis added to the call stack. - The main thread starts resolving the module identifier
fs. - The main thread wraps the contents of
fsin a function and executes it, a function execution context forfsis added to the call stack. - The
module.exportsobject is returned and assigned tofs. - The main thread removes function execution context for
fsfrom the call stack. - The main thread removes function execution context for
requirefrom the call stack. - The main thread executes
fs.readFilefunction call, a function execution context forfs.readFileis added to the call stack. - The main thread initiates a non-blocking file system operation to read the current file.
- The main thread moves the
fs.readFilecallback function to the I/O queue. - The main thread removes the function execution context for the first
fs.readFilefrom the call stack. - The main thread executes
requirefunction call, a function execution context forrequireis added to the call stack. - The main thread starts resolving the module identifier
http. - The main thread wraps the contents of
httpin a function and executes it, a function execution context forhttpis added to the call stack. - The
module.exportsobject is returned and assigned tohttp. - The main thread removes function execution context for
httpfrom the call stack. - The main thread removes function execution context for
requirefrom the call stack. - The main thread executes
http.getfunction call, a function execution context forhttp.getis added to the call stack. - The main thread initiates initiates an HTTP GET request.
- The main thread moves the
http.getcallback function to the I/O queue. - The main thread removes the function execution context for the first
http.getfrom the call stack. - The main thread executes
setTimeoutfunction call, a function execution context forsetTimeoutis added to the call stack. - The main thread adds the
setTimeoutcallback function to the timer queue. - The event loop continuously checks the timer queue. When the specified delay has elapsed, the callback function is moved to the appropriate phase of the event loop.
- The main thread removes the function execution context for
setTimeoutfrom the call stack. - The main thread executes
setImmediatefunction call, a function execution context forconsole.logis added to the call stack. - The main thread moves the
setImmediatecallback function to the check queue. - The main thread removes function execution context for
setImmediatefrom the call stack. - The main thread executes
process.nextTickfunction call, a function execution context forprocess.nextTickis added to the call stack. - The main thread moves the
process.nextTickcallback function to the next tick queue. - The main thread removes the function execution context for
process.nextTickfrom the call stack. - The main thread executes
queueMicrotaskfunction call, a function execution context forqueueMicrotaskis added to the call stack. - The main thread moves the
queueMicrotaskcallback function to the microtask queue. - The main thread removes the function execution context for
queueMicrotaskfrom the call stack. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"End"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - Once all the synchronous code has executed, the main thread removes the global execution context from the call stack.
- The call stack is now empty, waiting for asynchronous callbacks to be executed.
- The event loop starts processing the asynchronous callbacks that have been registered.
- The first loop
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for
process.nextTickcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"nextTick callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The event loop removes the function execution context for
process.nextTickcallback function from the call stack. - The event loop pushes the task from the microtask queue onto the call stack and creates a new function execution context for
queueMicrotaskcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"queueMicrotask callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes the function execution context for
queueMicrotaskcallback function from the call stack.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for
- Timers Phase
- The event loop pushes the task from the timer queue onto the call stack and creates a new function execution context for
setTimeoutcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Timeout callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes the function execution context for
setTimeoutcallback function from the call stack. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The event loop pushes the task from the timer queue onto the call stack and creates a new function execution context for
- Pending Callbacks Phase
- No pending callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Poll Phase
- The file reading operation isn't finished.
- The HTTP request is sent over the network and waits for the server response.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Check Phase
- The event loop pushes the task from the check queue onto the call stack and creates a new function execution context for
setImmediatecallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Check callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes the function execution context for
setImmediatecallback function from the call stack. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The event loop pushes the task from the check queue onto the call stack and creates a new function execution context for
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
- The event loop will continue to loop.
- The next loop
- The first loop starts by running the microtasks queue.
- No microtasks to execute.
- Timers Phase
- No timeout callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Pending Callbacks Phase
- The file reading operation is finished, but its callback is not yet marked to be executed because IO callbacks get queued up only at the IO Poll Phase.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Poll Phase
- The
fs.readFilecallback event is collected and added to the I/O queue. - When the response headers from the server are received, the event loop pushes the task from the I/O queue onto the call stack and creates a new function execution context for
http.getcallback function. - The server
localhostresponds HTTP GET request, the data starts arriving in chunks. - The event loop executes the data event listener call, a function execution context for data event listener is added to the call stack.
- The event loop moves the calbback function for data event listener to the event queue (task queue).
- Each chunk of data triggers a data event on the response object.
- Once the event loop detects the data event, the event loop will move the callback function for data event listener from the event queue (task queue) to the call stack to be executed and create a new function execution context for callback function.
- The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Data event listener callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes function execution context for callback function from the call stack.
- The data event listener also has no more code to run.
- The event loop removes function execution context for data event listener from the call stack.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue.
- The event loop will continue to loop.
- The next loop
- The first loop starts by running the microtasks queue.
- No microtasks to execute.
- Timers Phase
- No timeout callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Pending Callbacks Phase
- The event loop pushes the task from the I/O queue onto the call stack and creates a new function execution context for
fs.readFilecallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Pending callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes the function execution context for
fs.readFilecallback function from the call stack. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The event loop pushes the task from the I/O queue onto the call stack and creates a new function execution context for
- Poll Phase
- No I/O events to process.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue.
Close Callbacks Phase
The close callbacks phase is the last phase of the Node.js event loop. The close callback phase is where callbacks from the close event of a socket and the closing of an HTTP server run.
The close callbacks phase is designed to handle cleanup operations related to resource closure, such as the closing of TCP connections, file descriptors, and other resources.
Here's an example:
console.log('Start');
const fs = require('fs');
const readable = fs.createReadStream(__filename);
readable.on('data', (chunk) => {
console.log('Data event listener');
});
readable.on('close', () => {
console.log('Close callback');
});
const http = require("http");
http.get("http://localhost", (res) => {
console.log("Poll callback");
res.on("data", (chunk) => {
// Do something with the data
console.log("Data event listener callback");
});
});
setTimeout(() => {
console.log('Timeout callback');
}, 0);
setImmediate(() => {
console.log("Check callback");
});
process.nextTick(console.log, "nextTick callback");
queueMicrotask(() => console.log("queueMicrotask callback"));
console.log('End');
The output depends on which operation finishes first, the HTTP request or the file reading operation.
The output would be:
Start
End
nextTick callback
queueMicrotask callback
Timeout callback
Check callback
Poll callback
Data event listener callback
Pending callback
Or:
Start
End
nextTick callback
queueMicrotask callback
Timeout callback
Check callback
Data event listener
Poll callback
Data event listener callback
Close callback
The execution flow is as follows:
- The mainline
- The main thread starts by creating the global execution context and pushes it onto the call stack.
- The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"Start"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - The main thread executes
requirefunction call, a function execution context forrequireis added to the call stack. - The main thread starts resolving the module identifier
fs. - The main thread wraps the contents of
fsin a function and executes it, a function execution context forfsis added to the call stack. - The
module.exportsobject is returned and assigned toreadable. - The main thread removes function execution context for
fsfrom the call stack. - The main thread removes function execution context for
requirefrom the call stack. - The main thread executes
fs.createReadStreamfunction call, a function execution context forfs.createReadStreamis added to the call stack. - The main thread initiates a non-blocking file system operation to read the current file.
- This function is synchronous, meaning it runs immediately and returns a Readable stream object assigned to the
readable. - The main thread moves the
fs.createReadStreamcallback function to the I/O queue. - The main thread removes the function execution context for the first
fs.createReadStreamfrom the call stack. - The main thread executes
readable.onfunction call, a function execution context forreadable.onis added to the call stack. - The main thread moves the callback function to the event queue (task queue) which will be invoked whenever a chunk of data is available to be read from the stream.
- This callback is an asynchronous event listener, meaning it will be called asynchronously whenever the 'data' event is emitted.
- The main thread moves the
readable.oncallback function to the I/O queue. - The main thread executes the second
readable.onfunction call, a function execution context forreadable.onis added to the call stack. - The main thread moves the callback function to the event queue (task queue) which will be invoked when the stream is closed.
- This callback is also asynchronous and will be called when the 'close' event is emitted.
- The main thread moves the
readable.oncallback function to the I/O queue. - The main thread executes
requirefunction call, a function execution context forrequireis added to the call stack. - The main thread starts resolving the module identifier
http. - The main thread wraps the contents of
httpin a function and executes it, a function execution context forhttpis added to the call stack. - The
module.exportsobject is returned and assigned tohttp. - The main thread removes function execution context for
httpfrom the call stack. - The main thread removes function execution context for
requirefrom the call stack. - The main thread executes
http.getfunction call, a function execution context forhttp.getis added to the call stack. - The main thread initiates initiates an HTTP GET request.
- The main thread moves the
http.getcallback function to the I/O queue. - The main thread removes the function execution context for the first
http.getfrom the call stack. - The main thread executes
setTimeoutfunction call, a function execution context forsetTimeoutis added to the call stack. - The main thread adds the
setTimeoutcallback function to the timer queue. - The event loop continuously checks the timer queue. When the specified delay has elapsed, the callback function is moved to the appropriate phase of the event loop.
- The main thread removes the function execution context for
setTimeoutfrom the call stack. - The main thread executes
setImmediatefunction call, a function execution context forconsole.logis added to the call stack. - The main thread moves the
setImmediatecallback function to the check queue. - The main thread removes function execution context for
setImmediatefrom the call stack. - The main thread executes
process.nextTickfunction call, a function execution context forprocess.nextTickis added to the call stack. - The main thread moves the
process.nextTickcallback function to the next tick queue. - The main thread removes the function execution context for
process.nextTickfrom the call stack. - The main thread executes
queueMicrotaskfunction call, a function execution context forqueueMicrotaskis added to the call stack. - The main thread moves the
queueMicrotaskcallback function to the microtask queue. - The main thread removes the function execution context for
queueMicrotaskfrom the call stack. - The main thread executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The main thread logs
"End"to the console. - The main thread removes function execution context for
console.logfrom the call stack. - Once all the synchronous code has executed, the main thread removes the global execution context from the call stack.
- The call stack is now empty, waiting for asynchronous callbacks to be executed.
- The event loop starts processing the asynchronous callbacks that have been registered.
- The first loop
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for
process.nextTickcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"nextTick callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The event loop removes the function execution context for
process.nextTickcallback function from the call stack. - The event loop pushes the task from the microtask queue onto the call stack and creates a new function execution context for
queueMicrotaskcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"queueMicrotask callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes the function execution context for
queueMicrotaskcallback function from the call stack.
- The event loop pushes the task from the nextTick queue onto the call stack and creates a new function execution context for
- Timers Phase
- The event loop pushes the task from the timer queue onto the call stack and creates a new function execution context for
setTimeoutcallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Timeout callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes the function execution context for
setTimeoutcallback function from the call stack. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The event loop pushes the task from the timer queue onto the call stack and creates a new function execution context for
- Pending Callbacks Phase
- No pending callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Poll Phase
- The event loop waits for data from streams.
- The HTTP request is sent over the network and waits for the server response.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Check Phase
- The event loop pushes the task from the check queue onto the call stack and creates a new function execution context for
setImmediatecallback function. - The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Check callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes the function execution context for
setImmediatecallback function from the call stack. - The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The event loop pushes the task from the check queue onto the call stack and creates a new function execution context for
- Close Callbacks Phase
- No close callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue. The nextTick queue gets priority over the microtask queue.
- The event loop will continue to loop.
- The next loop
- The first loop starts by running the microtasks queue.
- No microtasks to execute.
- Timers Phase
- No timeout callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Pending Callbacks Phase
- No pending callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Poll Phase
- When a chunk of data is received, the event loop will move the callback function for data event listener from the event queue (task queue) to the call stack to be executed and create a new function execution context for callback function.
- Each chunk of data triggers a data event on the readable stream object.
- The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Data event listener"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes function execution context for callback function from the call stack.
- When the response headers from the server are received, the event loop pushes the task from the I/O queue onto the call stack and creates a new function execution context for
http.getcallback function. - The server
localhostresponds HTTP GET request, the data starts arriving in chunks. - The event loop executes the data event listener call, a function execution context for data event listener is added to the call stack.
- The event loop moves the calbback function for data event listener to the event queue (task queue).
- Each chunk of data triggers a data event on the response object.
- Once the event loop detects the data event, the event loop will move the callback function for data event listener from the event queue (task queue) to the call stack to be executed and create a new function execution context for callback function.
- The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Data event listener callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes function execution context for callback function from the call stack.
- The data event listener also has no more code to run.
- The event loop removes function execution context for data event listener from the call stack.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Check Phase
- No check callbacks to execute.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- Close Callbacks Phase
- When the entire file is read, the event loop will move the callback function for close event listener from the event queue (task queue) to the call stack to be executed and create a new function execution context for callback function.
- The event loop executes
console.logfunction call, a function execution context forconsole.logis added to the call stack. - The event loop logs
"Close callback"to the console. - The event loop removes function execution context for
console.logfrom the call stack. - The callback function has no more code to run.
- The event loop removes function execution context for callback function from the call stack.
- The event loop checks for any new callbacks added to the microtasks queue.
- If no any new callbacks added to the microtasks queue, the event loop continues to next phase.
- The first loop starts by running the microtasks queue.

