The NodeJS event loop is different from the browser's event loop mechanism. Before explaining it, you need to lay a little bit of other knowledge.

Asynchronous I/O

I/O refers to the IO (data in and out) capabilities provided by the operating system, such as keyboard input, there will be a special data output interface on the display, this interface will enter the operating system level downward, and the operating system system will provide many I/Od capabilities, such as disk read and write, DNS queries, database connections, network requests, etc.


I/O can be regarded as the data interaction between the upper-layer application and the lower-layer system. The upper-layer depends on the lower-layer, and the upper-layer can also transform the capabilities provided by the lower-layer. According to whether it is asynchronously blocked, it can be divided into asynchronous non-blocking asynchronous I/O Model and the synchronous I/O model of synchronous blocking. For example, readFile of NodeJS is an asynchronous non-blocking interface, and readFileSync is a synchronous blocking interface.

NodeJS Architecture


picture

This picture is the NodeJS architecture. NodeJS is divided into four layers, namely the application layer, the V8 engine layer, the NodeJS API layer and the libuv layer.

  • Application layer: the JavaScript interaction layer, the common ones are NodeJS modules, such as http, fs

  • V8 engine layer: use the V8 engine to parse JavaScript syntax, and then interact with the lower-level API

  • Node API layer: Provide system calls for upper-level modules, generally implemented by C language, and interact with the operating system

  • libuv layer: It is the bottom encapsulation of cross-platform, realizes event loop, file operation, etc. It is the core of NodeJS to achieve asynchronous

event loop

NodeJS performs non-blocking I/O operations, and although JavaScript is single-threaded, since most cores are multi-threaded, NodeJs will load operations into the system core whenever possible. So it is possible to handle multiple operations performed in the background, when one of its operations completes, the kernel notifies NodeJS so that Node.js can add the corresponding callback to the polling queue for eventual execution.

NodeJS will initialize the event loop when it starts up, and each event loop will contain 6 loop stages

┌────────────────────────┐
┌─>│ timers │
│ └────────────┬────── ──────┘
│ ┌──────────┴──────────────┐
│ │ I/O callbacks │
│ └──────── ──┬──────────────┘
│ ┌────────────┴────────────────┐
│ │ idle, prepare │
│ └ ────────────┬──────────────┘ ┌─────────────────┐
│ ┌──────── ───┴────────────┐ │ incoming: │
│ │ poll │<──────┤ connections, │
│ └──────────┬── ──────────┘ │ data, etc. │
│ ┌────────────┴──────────────┐ └────── ──────────┘
│ │ check │
│ └────────────┬──────────────┘
│ ┌──────── ──┴────────────┐
└──┤ close callbacks │
└──────────────────────────┘

The following is a detailed description of the operations performed in several stages.

timers stage

At this stage, the scheduled callbacks of setTimeOut(callback) and setInterval(callback) are executed, and the time specified by the timer is not the exact time of the callback execution, but a lower limit. After the specified time, timers will execute the callback as early as possible. And delays due to system scheduling or the execution of other callbacks

I/O callbacks stage

This phase performs callbacks for certain system operations, such as types of TCP errors. For example, when a TCP connection is rejected, the callback of this type of operation will be executed in the I/O callback stage. This does not mean that all I/O callbacks are executed in this stage. In fact, the I/O callback will be processed in the poll stage.

idle, prepare stage:

This stage is only used internally by node;

poll phase: get new I/O events

The poll phase has two main functions: 

(1) Execute the callback of timers whose lower limit time has reached, 

(2) Then process the events in the poll queue.

check stage:

This phase allows callbacks to be executed immediately after the poll phase ends. If the poll phase is idle and there is a callback set by setImmediate(), the event loop will go to the check phase instead of waiting.

close callbacks stage:

For example, the callback of socket.on('close', callback) will be executed at this stage;

Reference documentation

  • Node.js event loop, timers and process.nextTick()

  • In-depth analysis of Node.js event loop and message queue