This article will take you to understand the event loop mechanism in node. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to everyone.

Front-end development is inseparable from JavaScript. JavaScript is a web front-end language, mainly used in web development and parsed and executed by the browser. The role of js is not only limited to front-end development, it can also be used for server-side development - nodejs. As a front-end person with ideals and ambitions, if you want to expand your horizons and master a server-side development language, nodejs is a very good choice.
Related recommendations: "nodejs Tutorial"
Because you have mastered the js development method, it is easy to get started with node, and the npm package management tool also greatly improves the development experience. Nodejs is famous for its asynchronous non-blocking I/O working method, and its processing mechanism is called the event loop.
Understanding the node event loop mechanism can better understand node's event processing method and the execution timing of asynchronous events. This article mainly explains the event loop mechanism of nodejs and lays the foundation for subsequent learning of node.
1. node VS javascript
As mentioned earlier, Javascript is a web front-end language, mainly used in web development, and is parsed and executed by the browser, while node .js is a JavaScript runtime environment based on the Chrome V8 engine. Therefore, nodejs is not a language, a library, or a framework, but a js runtime environment. Simply put, node can parse and execute js code. In the past, only browsers could parse and execute JS, but now node can make JS run completely without the browser.
There are many differences between node.js and browser js. For example, js in the browser includes ecmascript, BOM, and DOM, but js in nodejs does not have BOM and DOM, only emcscript. And the js execution environment of node provides some server-level operation APIs for js, such as: file reading and writing, network service construction, network communication, http server, etc. Most of these APIs are packaged into core modules. In addition, the event loop mechanism of node is different from the event loop mechanism of browser js.
2. JavaScript event loop
Everyone is already very clear about the js event loop in the browser. For the sake of comparison, I will briefly mention it here.

When js is executed, synchronous and asynchronous tasks enter different execution environments respectively. Synchronous tasks enter the main thread, that is, the main execution stack, and asynchronous tasks (ajax requests, settimeout, setinterval, poromise.resolve(), etc.) enter the task queue. . Different asynchronous tasks will be pushed into different task queues, such as ajax requests, settimeout, setinterval, etc. These tasks will be pushed into the macro task queue (Macro Task), while the Promise function will be pushed into the micro task queue (Micro Task). . The overall event loop process is as follows:
When the synchronous code is executed, the main execution stack becomes empty and preparations begin to execute asynchronous tasks.
The main thread will check whether the microtask queue is empty. If it is not empty, it will traverse all the microtasks in the queue to execute them, clear the microtask queue, and then check the macro Task queue. If the microtask queue is empty, proceed directly to the next step.
The main thread traverses the macro task queue and executes the first macro task in the macro task queue. If it encounters a macro task or micro task during the execution, it will continue to process them. Push it into the corresponding task queue. Every time a macro task is executed, the micro task queue must be traversed and cleared.
Perform rendering operations and update the view
Start the next event loop and repeat the above steps until the two task queues are cleared
In order to deepen the impact, take a small example and look at the following code What will be output:
var le=Promise.resolve(2);
console.log(le)
console.log('3')
Promise.resolve().then(()=>{
console.log('Promise1')
setTimeout(()=>{
console.log('setTimeout2')
},0)
})
setTimeout(()=>{
console.log('setTimeout1')
Promise.resolve().then(()=>{
console.log('Promise2')
})
},0);Use the above event loop process to analyze:
- js main process execution code encounters Promise.resolve(2), it will be executed immediately, and 2 will be changed. into a promise object, and then console.log(le) prints out the le variable, print----->Promise {
: 2}; - console.log('3') , print ----->3
- Then continue the execution and encounter Promise.resolve().then, which is an asynchronous microtask function, pushed to the microtask stack
- A function encounters setTimeout and pushes it to the macro task queue. At this point, the main process is empty.
- Check the micro task queue and find Promise.resolve().then, so print ----->promise1 and encounter again to a timer, push it to the end of the macro task queue, the micro task queue is empty
- Check the macro task queue, take the first macro task to execute, print ----->setTimeout1, and encounter again Promise.resolve().then, push it to the microtask queue
- before starting the next macrotask, the microtask will be cleared, so after setTimeout1 is printed, the microtask queue will be checked, so ---> ;promise2
- The next round of event loop takes the current first task of the macro task queue and executes it, then prints and prints ----->setTimeout2. At this point, both the macro task and micro task queues have been cleared. , the event loop ends
So the output result is: Promise {
The execution result in the browser is as follows:

3. Node event loop
There are total event loops of node Six stages, these six stages will be executed in order in an event loop until the event processing is completed. The sequence diagram of the six stages is as follows:

六个阶段分别是:
- timers 阶段:这个阶段执行timer(setTimeout、setInterval)的回调
- I/O callbacks 阶段:执行一些系统操作的回调(比如网络通信的错误回调);
- idle, prepare 阶段:仅node内部使用,可忽略
- poll 阶段:获取新的I/O事件, 适当的条件下node将阻塞在这里
- check 阶段:执行 setImmediate() 的回调
- close callbacks 阶段:执行 socket 的 close 事件回调,如果一个socket或handle被突然关掉(比如socket.destroy()),close事件将在这个阶段被触发
事件循环中,每当进入某一个阶段,都会从该阶段对应的回调队列中取出函数去执行。当队列为空或者执行的回调函数数量到达系统设定的阈值,该阶段就会终止,然后检查NextTick队列和微任务队列,将其清空,之后进入下一个阶段。
这里面比较关键的是poll阶段:
- poll队列不为空的时候,事件循环会遍历队列并同步执行回调,直到队列清空或执行回调数达到系统上限。
- poll队列为空的时候,就会有两种情况:
- 如果代码中存在setImmediate()回调,那么事件循环直接结束poll阶段进入check阶段来执行check队列里的回调;
- 如果不存在setImmediate()回调,会等待回调被加入到队列中并立即执行回调,这里同样会有个超时时间设置防止一直等待下去,如果规定时间内有定时器函数进入队列,则返回到timer阶段,执行定时器回调,否则在poll阶段等待回调进入队列。
同样的举个大大的,看看以下代码会输出什么:
console.log('start')
setTimeout(() => {
console.log('timer1')
Promise.resolve().then(function() {
console.log('promise1')
})
}, 0)
setTimeout(() => {
console.log('timer2')
Promise.resolve().then(function() {
console.log('promise2')
})
}, 0)
Promise.resolve().then(function() {
console.log('promise3')
})
console.log('end')利用node事件循环分析呗:
- 先执行同步任务,打印start,end
- 进入timer阶段前,清空NextTick和micro队列,所以打印promise3
- 进入timer阶段,打印timer1,并发现有一个微任务,立即执行微任务,打印promise1
- 仍然在timer阶段,执行下个宏任务,打印timer2,同样遇到微任务,立即执行,打印promise2
因此输出顺序是:start,end,promise3,timer1,promise1,timer2,promise2,如果能正确回答出来说明对node的循环机制有了大体的了解,实际node输出结果确实是这样:

那如下代码会输出什么呢?
process.nextTick(function(){
console.log(7);
});
new Promise(function(resolve){
console.log(3);
resolve();
console.log(4);
}).then(function(){
console.log(5);
});
process.nextTick(function(){
console.log(8);
});继续分析:
- process.nextTick会将任务推进至nextTick队列,promise.then会把任务推至micro队列,上面提到过每次一个宏任务执行完,执行下一个宏任务之前需要清空nextTick队列和micro队列,同样的一个阶段执行完,进入下一个阶段之前也需要nextTick队列和micro队列,并且nextTick队列优先级高于micro队列
- 先执行同步代码,打印3,4
- 执行nextTick队列,打印7,8
- 再执行micro队列,打印5
因此最终输出是:3,4,7,8,5,需要记住,process.nextTick 永远大于 promise.then的优先级
还有一个大家很容易混淆的点就是setTimout和setImmediate的执行时机,根据上面描述的node事件循环机制,setImmediate()应该在check阶段执行 与 而setTimeout在timer阶段执行,理论上setTimout比setImmediate先执行,看下面的代码:
setTimeout(() => console.log(1),0); setImmediate(() => console.log(2));
执行结果是什么?1,2 还是 2,1,其实都有可能,看实际node运行的结果:

可以看到两次执行的结果不一样,为什么呢?原因在于即使setTimeout的第二个参数默认为0,但实际上,Node做不到0秒就执行其回调,最少也要4毫秒。那么进入事件循环后,如果没到4毫秒,那么timers阶段就会被跳过,从而进入check阶段执行setImmediate回调,此时输出结果是:2,1;
如果进入事件循环后,超过4毫秒(只是个大概,具体值并不确定),setTimeout的回调会出现在timer阶段的队列里,回调将被执行,之后再进入poll阶段和check阶段,此时输出结果是:1,2
那如果两者在I/O周期内调用,谁先执行呢?看一下代码:
const fs = require('fs')
fs.readFile('./test.txt', 'utf8' , (err, data) => {
if (err) {
console.error(err)
return
}
setTimeout(() => {
console.log('timeout');
}, 0);
setImmediate(() => {
console.log('immediate');
});
})实际上,node中输出的结果总是immediate先输出,timeout后输出。因为I/O回调是在poll阶段执行,当回调执行完毕之后队列为空,发现存在setImmediate的回调就会进入check阶段,执行完毕后,再进入timer阶段。
四、总结
本文结合代码示例,对node的事件循环机制做了比较详细描述。通过这篇文章,应该可以了解浏览器的事件循环机制是怎样的,node的循环机制是怎样的,以及nextTick和micro队列的优先级,setTimout和setImmediate执行时机等一些容易混淆的知识点。文章中不足和不对之处,欢迎在评论区交流讨论,一起探索,谢谢。
更多编程相关知识,请访问:编程入门!!
The above is the detailed content of Detailed explanation of the event loop mechanism in nodejs. For more information, please follow other related articles on the PHP Chinese website!
JavaScript Object Models: Deep Copying, Shallow Copying, and Considerations for Java SerializationJul 23, 2025 am 04:07 AMShallow copy only copies the top-level properties of the object, nested reference types share the same memory address, and modifying the copy will affect the original object; deep copy recursively copies all levels to ensure complete independence. For example, using Object.assign or extension operators is a shallow copy, modifying nested objects will reflect the original object; while JSON.parse(JSON.stringify(obj)) or Lodash's _.cloneDeep() can achieve deep copy to avoid mutual influence. In addition, deep copying requires attention to special types of processing such as functions, circular references, and Date. When communicating across languages, the impact of Java serialization on data structures must also be considered.
How to select an HTML element by class or tag name in JS?Jul 23, 2025 am 04:01 AMSelecting HTML elements in JavaScript can be achieved in three ways: 1. Use getElementsByClassName to select by class name, return dynamic HTMLCollection, you need to write the class name, such as 'box', and access the first element through boxes[0]; 2. Use getElementsByTagName to select by tag name, and also return dynamic HTMLCollection, suitable for batch operations such as modifying all li styles; 3. Use querySelectorAll to select by CSS selector, support more complex selection logic, return static NodeList, if only the first match is required, you can use querySe
Working with Dates in JavaScript: A Complete GuideJul 23, 2025 am 03:59 AMJavaScript's date processing requires attention to creating, getting set values, formatting and time zone issues. 1. Create a Date object by using no parameters, timestamps, date strings or components; note that the month starts at 0 and the browser parses the strings may be inconsistent. 2. Use getDate, setDate and other methods to get/set the value, and use getTime() to compare the date. 3. Intl.DateTimeFormat can be used to ensure consistency, and third-party libraries can also be used. 4. UTC method should be used to deal with time zones to avoid confusion. The sending server recommends using UTC and converting it to the backend.
JavaScript Performance Optimization: Debouncing and ThrottlingJul 23, 2025 am 03:57 AMDebouncingdelaysfunctionexecutionuntilafterapauseinactivity,idealforsearchinputsandformvalidation;2.Throttlinglimitsexecutiontoonceperfixedinterval,perfectforscrollandmousemoveevents;bothreduceperformanceloadwhilepreservingUX.
Leveraging JavaScript Proxies and Reflect API for Advanced Metaprogramming with Java InteropJul 23, 2025 am 03:55 AMJavaScriptProxies and ReflectAPI can be used to enhance the interoperability of Java and JavaScript in Nashorn or GraalVM environments. 1. Use Proxy to intercept access to Java objects, such as recording attribute access logs or dynamically modifying the return value, and implementing it through get traps and Reflect.get; 2. You can proxie the Java class itself and control constructor calls through construct traps; 3. Use apply traps to automatically convert parameter types before calling Java methods to improve compatibility between JS and Java; 4. Reflect provides more consistent operation methods, such as Reflect.has
Implementing JavaScript Security Headers in Node.jsJul 23, 2025 am 03:48 AMThe method of setting up JavaScript security headers in Node.js applications is to use Helmet middleware to implement it through the backend. 1. Install and introduce the Helmet package and add it to the Express middleware chain to enable the default security headers; 2. Common security headers include CSP to prevent XSS attacks, X-Content-Type-Options to avoid MIME type guessing, X-Frame-Options to prevent click hijacking, HSTS to force HTTPS access, etc.; 3. CSP policies can be customized to meet external resource loading needs, but 'unsafe-inline' should be avoided, and Nonce or Hash is recommended instead; 4. Enable
Advanced JavaScript Readable and Writable StreamsJul 23, 2025 am 03:47 AMReadable and writable streams in JavaScript achieve efficient data transmission through chunking processing. 1. ReadableStream is used to read data in asynchronously in blocks, suitable for large file reading, HTTP response and other scenarios; 2. WritableStream receives data and processes it, such as writing to files or recording logs; 3. Use the .pipe() method to automatically process back pressure, connecting readable and writable streams; 4. Transform stream can be converted during data flow; 5. In actual use, pay attention to error processing, back pressure control and correct ending of streams. Mastering these key points will help improve big data processing capabilities and performance.
How does hoisting work in JavaScript?Jul 23, 2025 am 03:45 AMVariable and function enhancement is the mechanism by which the JavaScript engine collects declarations into memory during the compilation phase, and does not really move the code. When a variable is declared using var, it will be promoted to the top of the scope, but the assignment remains in place; let and const will also be promoted, but will not be initialized, and it will enter a "temporary dead zone", and an error will be reported when access is reported. Function declarations will be fully promoted, including the function body, so they can be called before declaration; while the function expression only has the variable name promoted, and the function body is still in place. In actual development, suggestions are: 1. Declare variables at the top of the scope; 2. Priority is given to let and const; 3. Avoid calling function expressions or arrow functions before the function; 4. Do not repetitively declare functions and variables with the same name. Understanding the lifting mechanism helps


Hot AI Tools

Undress AI Tool
Undress images for free

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

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

Clothoff.io
AI clothes remover

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

Hot Article

Hot Tools

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

Atom editor mac version download
The most popular open source editor

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.








