In-depth understanding of Node event loop (EventLoop) mechanism
The main thread reads events from the "task queue". This process is cyclic, so the entire running mechanism is also called Event Loop. The following article will help you master the eventloop in Node.js. I hope it will be helpful to you!
Although js
can be executed in the browser and node
, their event loop mechanism is not the same. And there is a big difference.
Overview of the EventLoop mechanism
Before talking about the Node
event loop mechanism, let us first discuss two issues
Why should we learn the event loop mechanism?
Learning the event loop can allow developers to understand how JavaScript
operates.
What does the event loop mechanism do?
The event loop mechanism is used to manage when the callback function of the asynchronous API returns to the main thread for execution .
Node.js uses an asynchronous IO model. The synchronous API is executed in the main thread, the asynchronous API is executed in the thread maintained by the underlying C, and the callback function of the asynchronous API will also be executed in the main thread. [Recommended related tutorials: nodejs video tutorial, Programming teaching]
When a Javascript application is running, when can the callback functions of many asynchronous APIs return to the main thread? What about calls? This is what the event loop mechanism does, managing when the callback function of the asynchronous API returns to the main thread for execution.
The six stages of EventLoop
The event loop in Node
is divided into six stages.
There is a queue at each stage in the event loop to store the callback functions to be executed. The event loop mechanism will execute them in a first-in, first-out manner until the queue is null.
These six stages all store asynchronous callback functions, so it is still necessary to execute the main thread synchronization code first, and then poll these six stages after the synchronization code is executed.
Next, let’s take a detailed look at what is stored in these six stages
Timers
Timers
: Callback function (setlnterval, setTimeout) used to store timers.
Pendingcallbacks
Pendingcallbacks
: Execute callback functions related to the operating system, such as the callback function that monitors port operations when starting a server-side application. Called here.
idle, prepare
idle, prepare
: used internally by the system. (We programmers don’t need to worry about this)
Poll
Poll
: Stores the callback function queue for 1/O operations, such as file read and write operations callback function.
Special attention needs to be paid at this stage. If there are callback functions in the event queue, they will be executed until the queue is cleared. , otherwise the event loop will stay at this stage for a while to wait for a new callback function to enter.
But for this waiting is not certain, but depends on the following two conditions:
- If there is something to be executed in the setlmmediate queue (check phase) adjustment function. In this case there will be no waiting.
- There is a callback function to be executed in the timers queue, and there will be no waiting in this case. The event loop will move to the check phase, then to the Closingcallbacks phase, and finally from the timers phase to the next loop.
Check
Check
: Stores the callback function of setlmmediate.
Closingcallbacks
Closingcallbacks
: Execute callbacks related to closing events, such as callback functions for closing database connections, etc.
Macro tasks and micro tasks
Like js
in the browser, the asynchronous code in node
is also divided into They are macrotasks and microtasks, but the execution order between them is different.
Let’s take a look at the macro tasks and micro tasks in Node
Macro tasks
setlnterval
setimeout
setlmmediate
I/O
Microtasks
- ##Promise.then
- Promise.catch
- Promise.finally
- process.nextTick
node, for microtasks and macros What is the order of execution of tasks?
Execution sequence of microtasks and macrotasks
In node
, the callback function of the microtask is placed in the microtask queue, and the callback function of the macrotask is placed in the macro task queue.
Microtasks have higher priority than macrotasks. When there is an executable callback function in the microtask event queue, the event loop will pause and enter the next stage of the event loop after executing the callback function of the current stage, and will immediately enter the microtask's event queue to start executing the callback function. When the callback function in the microtask queue is executed, the event loop will enter the next segment and start executing the callback function.
There is another point we need to pay special attention to when it comes to microtasks. That is, although nextTick
is also a micro-task, its priority is higher than other micro-tasks. When executing a micro-task, only after all callback functions in nextlick
are executed. Other microtasks will start to be executed.
In general, when the main thread synchronization code is executed, the microtasks will be cleared first (if the microtasks continue to generate microtasks, they will be cleared again), and then go to the next event loop stage. And the execution of microtasks is interspersed among the six stages of the event loop. That is, before each event loop enters the next stage, it will determine whether the microtask queue is empty. If it is empty, it will enter the next stage. Otherwise, the microtasks will be cleared first. queue.
Let’s use code practice to verify what we said above.
Code example
Execute synchronization first and then asynchronously
After the Node
application starts , will not enter the event loop immediately, but will execute the synchronous code first, starting from top to bottom. The synchronous API will be executed immediately, and the asynchronous API will be handed over to the thread maintained by C for execution. The callback function of the asynchronous API will be registered to the corresponding event queue. middle. When all synchronization codes are executed, the event loop will be entered.
console.log("start"); setTimeout(() => { console.log("setTimeout 1"); }); setTimeout(() => { console.log("setTimeout 2"); }); console.log("end");
Let’s look at the execution results
You can see that the synchronous code is executed first, and then the event loop is entered to execute the asynchronous code. In The timers
stage executes two setTimeout
callbacks.
Will setTimeout be executed before setImmediate?
We know that setTimeout
is executed in the timers
stage, setImmediate
is executed in the check
phase. And the event loop starts from the timers
phase. Therefore, setTimeout
will be executed first and then setImmediate
.
Is the above analysis correct?
Let’s look at the example
console.log("start"); setTimeout(() => { console.log("setTimeout"); }); setImmediate(() => { console.log("setImmediate"); }); const sleep = (delay) => { const startTime = +new Date(); while (+new Date() - startTime < delay) { continue; } }; sleep(2000); console.log("end");
Execute the above code, the output is as follows
Execute firstsetTimeout
then execute setImmediate
Next let’s transform the above code, remove the delayer, and see what will be output
setTimeout(() => { console.log("setTimeout"); }); setImmediate(() => { console.log("setImmediate"); });
We ran it seven times and you can see it Twice, setImmediate
was run first. What happened? Isn’t it first the timers
stage and then the check
stage? How could it change?
In fact, it depends on whether the asynchronous callback is fully ready when entering the event loop. For the initial example, because there is a delay of 2000 milliseconds, the setTimeout
callback must be ready when entering the event loop. So the order of execution will not change. But for this example, because the main thread has no synchronization code to execute, it enters the event loop at the beginning. However, when entering the event loop, the callback of setTimeout
is not necessarily fully prepared, so it will There is a callback function that first executes the setImmediate
in the check
stage, and then executes the setTimeout
callback in the timers
stage of the next event loop.
Under what circumstances will the setImmediate
callback function take precedence over the setTimeout
callback for the same delay time?
It's actually very simple, just put these two in the Pendingcallbacks, idle, prepare, poll
between the timers
stage and the check
stage Any one of the stages will do. Because after these stages are executed, they will definitely go to the check
stage and then the timers
stage.
We take the poll
stage as an example and write these two in the IO operation.
const fs = require("fs"); fs.readFile("./fstest.js", "utf8", (err, data) => { setTimeout(() => { console.log("setTimeout"); }); setImmediate(() => { console.log("setImmediate"); }); });
We also execute it seven times. You can see that setImmediate
is executed first every time.
So in general, with the same delay time, setTimeout
is not 100% executed before setImmediate
.
先微任务再宏任务
主线程同步代码执行完毕后,会先执行微任务再执行宏任务。
我们来看下面的例子
console.log("start"); setTimeout(() => { console.log("setTimeout"); }); setImmediate(() => { console.log("setImmediate"); }); Promise.resolve().then(() => { console.log("Promise.resolve"); }); console.log("end");
我们运行一下看结果,可以看到它是先执行了微任务然后再执行宏任务
nextTick优于其它微任务
在微任务中nextTick
的优先级是最高的。
我们来看下面的例子
console.log("start"); setTimeout(() => { console.log("setTimeout"); }); setImmediate(() => { console.log("setImmediate"); }); Promise.resolve().then(() => { console.log("Promise.resolve"); }); process.nextTick(() => { console.log("process.nextTick"); }); console.log("end");
我们运行上面的代码,可以看到就算nextTick
定义在resolve
后面,它也是先执行的。
微任务穿插在各个阶段间执行
怎么理解这个穿插呢?其实就是在事件循环的六个阶段每个阶段执行完后会清空微任务队列。
我们来看例子,我们建立了timers、check、poll
三个阶段,并且每个阶段都产生了微任务。
// timers阶段 setTimeout(() => { console.log("setTimeout"); Promise.resolve().then(() => { console.log("setTimeout Promise.resolve"); }); }); // check阶段 setImmediate(() => { console.log("setImmediate"); Promise.resolve().then(() => { console.log("setImmediate Promise.resolve"); }); }); // 微任务 Promise.resolve().then(() => { console.log("Promise.resolve"); }); // 微任务 process.nextTick(() => { console.log("process.nextTick"); Promise.resolve().then(() => { console.log("nextTick Promise.resolve"); }); });
我们来执行上面的代码
可以看到,先执行微任务,再执行宏任务。先process.nextTick -> Promise.resolve
。并且如果微任务继续产生微任务则会再次清空,所以就又输出了nextTick Promise.resolve
。
接下来到timer
阶段,输出setTimeout
,并且产生了一个微任务,再进入到下个阶段前需要清空微任务队列,所以继续输出setTimeout Promise.resolve
。
接下来到check
阶段,输出setImmediate
,并且产生了一个微任务,再进入到下个阶段前需要清空微任务队列,所以继续输出setImmediate Promise.resolve
。
这也就印证了微任务会穿插在各个阶段之间运行。
总结
所以对于Node
中的事件循环你只需要背好一以下几点就可以了
当主线程同步代码执行完毕后才会进入事件循环
事件循环总共分六个阶段,并且每个阶段都包括哪些回调需要记清楚。
事件循环中会先执行微任务再执行宏任务。
微任务会穿插在这六个阶段之间执行,每进入到下个阶段前会清空当前的微任务队列。
微任务中
process.nextTick
的优先级最高,会优先执行。
更多node相关知识,请访问:nodejs 教程!
The above is the detailed content of In-depth understanding of Node event loop (EventLoop) mechanism. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



PHP and Vue: a perfect pairing of front-end development tools. In today's era of rapid development of the Internet, front-end development has become increasingly important. As users have higher and higher requirements for the experience of websites and applications, front-end developers need to use more efficient and flexible tools to create responsive and interactive interfaces. As two important technologies in the field of front-end development, PHP and Vue.js can be regarded as perfect tools when paired together. This article will explore the combination of PHP and Vue, as well as detailed code examples to help readers better understand and apply these two

In front-end development interviews, common questions cover a wide range of topics, including HTML/CSS basics, JavaScript basics, frameworks and libraries, project experience, algorithms and data structures, performance optimization, cross-domain requests, front-end engineering, design patterns, and new technologies and trends. . Interviewer questions are designed to assess the candidate's technical skills, project experience, and understanding of industry trends. Therefore, candidates should be fully prepared in these areas to demonstrate their abilities and expertise.

JavaScript tutorial: How to get HTTP status code, specific code examples are required. Preface: In web development, data interaction with the server is often involved. When communicating with the server, we often need to obtain the returned HTTP status code to determine whether the operation is successful, and perform corresponding processing based on different status codes. This article will teach you how to use JavaScript to obtain HTTP status codes and provide some practical code examples. Using XMLHttpRequest

Django is a web application framework written in Python that emphasizes rapid development and clean methods. Although Django is a web framework, to answer the question whether Django is a front-end or a back-end, you need to have a deep understanding of the concepts of front-end and back-end. The front end refers to the interface that users directly interact with, and the back end refers to server-side programs. They interact with data through the HTTP protocol. When the front-end and back-end are separated, the front-end and back-end programs can be developed independently to implement business logic and interactive effects respectively, and data exchange.

What is JPA? How is it different from JDBC? JPA (JavaPersistence API) is a standard interface for object-relational mapping (ORM), which allows Java developers to use familiar Java objects to operate databases without writing SQL queries directly against the database. JDBC (JavaDatabaseConnectivity) is Java's standard API for connecting to databases. It requires developers to use SQL statements to operate the database. JPA encapsulates JDBC, provides a more convenient and higher-level API for object-relational mapping, and simplifies data access operations. In JPA, what is an entity? entity

As a fast and efficient programming language, Go language is widely popular in the field of back-end development. However, few people associate Go language with front-end development. In fact, using Go language for front-end development can not only improve efficiency, but also bring new horizons to developers. This article will explore the possibility of using the Go language for front-end development and provide specific code examples to help readers better understand this area. In traditional front-end development, JavaScript, HTML, and CSS are often used to build user interfaces

Combination of Golang and front-end technology: To explore how Golang plays a role in the front-end field, specific code examples are needed. With the rapid development of the Internet and mobile applications, front-end technology has become increasingly important. In this field, Golang, as a powerful back-end programming language, can also play an important role. This article will explore how Golang is combined with front-end technology and demonstrate its potential in the front-end field through specific code examples. The role of Golang in the front-end field is as an efficient, concise and easy-to-learn

Introduction to the method of obtaining HTTP status code in JavaScript: In front-end development, we often need to deal with the interaction with the back-end interface, and HTTP status code is a very important part of it. Understanding and obtaining HTTP status codes helps us better handle the data returned by the interface. This article will introduce how to use JavaScript to obtain HTTP status codes and provide specific code examples. 1. What is HTTP status code? HTTP status code means that when the browser initiates a request to the server, the service
