search
HomeWeb Front-endJS TutorialNode JS - The Event Loop

Node JS - The Event Loop

We have discussed why Node JS is single-threaded and also multi-threaded in our article called "Node Internals". It’ll give you a solid foundation on Node’s architecture and set the stage for understanding the magic of the Event Loop!

Node js could be considered single-threaded because of the Event Loop. But, what is the event loop?

I always start with the restaurant analogy because I think it becomes easy to understand technical details.

So, In the restaurant main chef takes orders from the order list and gives them to the team of assistants. When food is ready the chef serves the food. If any VIP customers come then the chef prioritize this order.

If we take this analogy into our consideration then we can say that...

In the context of Node JS Event Loop.

  • Chef is the Event Loop that manages tasks and delegating work.

  • Team of Assistance is a worker thread or the OS that handles the execution of the delegated tasks to them.

  • Order List is a task queue for tasks waiting for their turn.

  • VIP customer is a Microtask that has high priority and is completed before regular tasks.

To, Understand Event Loop we have to first understand the difference between Microtasks and Macrotasks.

Microtask

Microtask means tasks that have some high priority and are executed after the currently executing Javascript code completes, but before moving to the next phase of the Event Loop.

Example:

  • process.nextTick
  • Promises (.then, .catch, .finally)
  • queueMicrotask

Macrotask

These are lower-priority tasks queued for execution at a later phase in the Event Loop.

Example:

  • setTimeout
  • setInterval
  • setImmediate
  • I/O operations

The Event Loop

When we run asynchronous tasks in Node.js, the Event Loop is at the heart of everything.

Thanks to the Event Loop, Node.js can perform non-blocking I/O operations efficiently. It achieves this by delegating time-consuming tasks to the operating system or worker threads. Once the tasks are completed, their callbacks are processed in an organized manner, ensuring smooth execution without blocking the main thread.

This is the magic that allows Node.js to handle multiple tasks concurrently while still being single-threaded.

Phases

There are six phases in an Event Loop and each phase has its own queue, which holds specific types of tasks.

1.Timers phase

In this phase timer related callbacks are handled such as setTimeout, and setInterval.

Node js checks the timer queue for callbacks whose delay has expired.

If a timer delay is met, its callback is added to this queue for execution.

console.log('Start');

setTimeout(() => {
  console.log('Timer 1 executed after 1 second');
}, 1000);

setTimeout(() => {
  console.log('Timer 2 executed after 0.5 seconds');
}, 500);

let count = 0;
const intervalId = setInterval(() => {
  console.log('Interval callback executed');
  count++;

  if (count === 3) {
    clearInterval(intervalId);
    console.log('Interval cleared');
  }
}, 1000);

console.log('End');

Output:

Start
End
Timer 2 executed after 0.5 seconds
Timer 1 executed after 1 second
Interval callback executed
Interval callback executed
Interval callback executed
Interval cleared

2.I/O callback phase

This phase's purpose is to execute callbacks for completed I/O (Input/Output) operations, such as reading or writing files, querying databases, handling network requests, and other asynchronous I/O tasks.

When you any asynchronous I/O operation in Node.js (like reading a file using fs.readFile) comes then, the operation is delegated to the operating system or worker threads. These I/O tasks are executed outside the main thread in a non-blocking manner. Once the task is completed, a callback function is triggered to process the results.

The I/O Callbacks Phase is where these callbacks are queued for execution once the operation finishes.

const fs = require('fs');

console.log('Start');

fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) {
    console.log('Error reading file:', err);
    return;
  }
  console.log('File contents:', data);
});

console.log('Middle');

setTimeout(() => {
  console.log('Simulated network request completed');
}, 0);

console.log('End');

Output

Start
Middle
End
Simulated network request completed
File contents: (contents of the example.txt file)

3.Idle phase

In this phase, no user-defined work is performed instead in this phase event loop gets ready for the next phases. only internal adjustments are done in this phase.

4.Poll phase

The Poll Phase checks whether there are pending I/O events (like network activity or file system events) that need to be processed. It will immediately execute the callbacks associated with these events.

If no I/O events are pending, the Poll Phase can enter a blocking state.

In this blocking state, Node.js will simply wait for new I/O events to arrive. This blocking state is what makes Node.js non-blocking: It waits until new I/O events trigger callback executions, keeping the main thread free for other tasks in the meantime.

Any callbacks for completed I/O operations (such as fs.readFile, HTTP requests, or database queries) are executed during this phase. These I/O operations may have been initiated in previous phases (like the Timers Phase or I/O Callbacks Phase) and are now completed.

If there are timers set with setTimeout or setInterval, Node.js will check if any timers have expired and if their associated callbacks need to be executed. If timers have expired, their callbacks are moved to the callback queue, but they will not be processed until the next phase, which is the Timers Phase.

const fs = require('fs');
const https = require('https');

console.log('Start');

fs.readFile('file1.txt', 'utf8', (err, data) => {
  if (err) {
    console.log('Error reading file1:', err);
    return;
  }
  console.log('File1 content:', data);
});

fs.readFile('file2.txt', 'utf8', (err, data) => {
  if (err) {
    console.log('Error reading file2:', err);
    return;
  }
  console.log('File2 content:', data);
});

https.get('https://jsonplaceholder.typicode.com/todos/1', (response) => {
  let data = '';
  response.on('data', (chunk) => {
    data += chunk;
  });
  response.on('end', () => {
    console.log('HTTP Response:', data);
  });
});

console.log('End');

Output:

Start
End
File1 content: (contents of file1.txt)
File2 content: (contents of file2.txt)
HTTP Response: (JSON data from the HTTP request)

5.Check phase

After the Poll Phase has completed its tasks. This phase mainly handles the execution of setImmediate callbacks, which are scheduled to run immediately after the I/O events are processed in the Poll Phase.

setImmediate callbacks are often used when you want to perform an action after the current event loop cycle, such as making sure some task is executed after the system is not busy processing I/O events.

The Check Phase has higher priority over the Timers Phase (which handles setTimeout and setInterval). This means that setImmediate callbacks will always be executed before any timers even if their timers have expired.

setImmediate guarantees that its callback will run after the current I/O cycle and before the next timer cycle. This can be important when you want to ensure that I/O-related tasks are completed first before running other tasks.

console.log('Start');

setTimeout(() => {
  console.log('Timer 1 executed after 1 second');
}, 1000);

setTimeout(() => {
  console.log('Timer 2 executed after 0.5 seconds');
}, 500);

let count = 0;
const intervalId = setInterval(() => {
  console.log('Interval callback executed');
  count++;

  if (count === 3) {
    clearInterval(intervalId);
    console.log('Interval cleared');
  }
}, 1000);

console.log('End');

Output:

Start
End
Timer 2 executed after 0.5 seconds
Timer 1 executed after 1 second
Interval callback executed
Interval callback executed
Interval callback executed
Interval cleared

6.close phase

The Close Callbacks Phase typically executes when an application needs to clean up before exiting or shutting down.

This phase deals with events and tasks that need to be executed once a system resource, like a network socket or file handle, is no longer needed.

Without this phase, an application might leave open file handles, network connections, or other resources, potentially leading to memory leaks, data corruption, or other issues.

const fs = require('fs');

console.log('Start');

fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) {
    console.log('Error reading file:', err);
    return;
  }
  console.log('File contents:', data);
});

console.log('Middle');

setTimeout(() => {
  console.log('Simulated network request completed');
}, 0);

console.log('End');

Output:

Start
Middle
End
Simulated network request completed
File contents: (contents of the example.txt file)

There is one more special phase in the Event Loop of Node JS.

Microtask Queue

process.nextTick() and promises to execute their callbacks in a special phase in the Event Loop.

process.nextTick() schedules a callback to be executed immediately after the current operation completes, but before the event loop continues to the next phase.

process.nextTick() is not part of any phase in the event loop. Instead, it has its own internal queue that gets executed right after the currently executing synchronous code and before any phase in the event loop is entered.

It's executed after the current operation but before I/O, setTimeout, or other tasks scheduled in the event loop.

Promises have lower priority than process.nextTick() and are processed after all process.nextTick() callbacks.

const fs = require('fs');
const https = require('https');

console.log('Start');

fs.readFile('file1.txt', 'utf8', (err, data) => {
  if (err) {
    console.log('Error reading file1:', err);
    return;
  }
  console.log('File1 content:', data);
});

fs.readFile('file2.txt', 'utf8', (err, data) => {
  if (err) {
    console.log('Error reading file2:', err);
    return;
  }
  console.log('File2 content:', data);
});

https.get('https://jsonplaceholder.typicode.com/todos/1', (response) => {
  let data = '';
  response.on('data', (chunk) => {
    data += chunk;
  });
  response.on('end', () => {
    console.log('HTTP Response:', data);
  });
});

console.log('End');

Output:

Start
End
File1 content: (contents of file1.txt)
File2 content: (contents of file2.txt)
HTTP Response: (JSON data from the HTTP request)

Now, You have an overall idea of how the Event Loop works.

I am giving you one question which answer you can give in the comments.

const fs = require('fs');

console.log('Start');

fs.readFile('somefile.txt', 'utf8', (err, data) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log('File content:', data);
});

setImmediate(() => {
  console.log('Immediate callback executed');
});

setTimeout(() => {
  console.log('Timeout callback executed');
}, 0);

console.log('End');

Thank you.

Waiting for your answer.

The above is the detailed content of Node JS - The Event Loop. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Is JavaScript Written in C? Examining the EvidenceIs JavaScript Written in C? Examining the EvidenceApr 25, 2025 am 12:15 AM

Yes, the engine core of JavaScript is written in C. 1) The C language provides efficient performance and underlying control, which is suitable for the development of JavaScript engine. 2) Taking the V8 engine as an example, its core is written in C, combining the efficiency and object-oriented characteristics of C. 3) The working principle of the JavaScript engine includes parsing, compiling and execution, and the C language plays a key role in these processes.

JavaScript's Role: Making the Web Interactive and DynamicJavaScript's Role: Making the Web Interactive and DynamicApr 24, 2025 am 12:12 AM

JavaScript is at the heart of modern websites because it enhances the interactivity and dynamicity of web pages. 1) It allows to change content without refreshing the page, 2) manipulate web pages through DOMAPI, 3) support complex interactive effects such as animation and drag-and-drop, 4) optimize performance and best practices to improve user experience.

C   and JavaScript: The Connection ExplainedC and JavaScript: The Connection ExplainedApr 23, 2025 am 12:07 AM

C and JavaScript achieve interoperability through WebAssembly. 1) C code is compiled into WebAssembly module and introduced into JavaScript environment to enhance computing power. 2) In game development, C handles physics engines and graphics rendering, and JavaScript is responsible for game logic and user interface.

From Websites to Apps: The Diverse Applications of JavaScriptFrom Websites to Apps: The Diverse Applications of JavaScriptApr 22, 2025 am 12:02 AM

JavaScript is widely used in websites, mobile applications, desktop applications and server-side programming. 1) In website development, JavaScript operates DOM together with HTML and CSS to achieve dynamic effects and supports frameworks such as jQuery and React. 2) Through ReactNative and Ionic, JavaScript is used to develop cross-platform mobile applications. 3) The Electron framework enables JavaScript to build desktop applications. 4) Node.js allows JavaScript to run on the server side and supports high concurrent requests.

Python vs. JavaScript: Use Cases and Applications ComparedPython vs. JavaScript: Use Cases and Applications ComparedApr 21, 2025 am 12:01 AM

Python is more suitable for data science and automation, while JavaScript is more suitable for front-end and full-stack development. 1. Python performs well in data science and machine learning, using libraries such as NumPy and Pandas for data processing and modeling. 2. Python is concise and efficient in automation and scripting. 3. JavaScript is indispensable in front-end development and is used to build dynamic web pages and single-page applications. 4. JavaScript plays a role in back-end development through Node.js and supports full-stack development.

The Role of C/C   in JavaScript Interpreters and CompilersThe Role of C/C in JavaScript Interpreters and CompilersApr 20, 2025 am 12:01 AM

C and C play a vital role in the JavaScript engine, mainly used to implement interpreters and JIT compilers. 1) C is used to parse JavaScript source code and generate an abstract syntax tree. 2) C is responsible for generating and executing bytecode. 3) C implements the JIT compiler, optimizes and compiles hot-spot code at runtime, and significantly improves the execution efficiency of JavaScript.

JavaScript in Action: Real-World Examples and ProjectsJavaScript in Action: Real-World Examples and ProjectsApr 19, 2025 am 12:13 AM

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

JavaScript and the Web: Core Functionality and Use CasesJavaScript and the Web: Core Functionality and Use CasesApr 18, 2025 am 12:19 AM

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version