Home > Article > Web Front-end > Detailed explanation of the event loop mechanism in nodejs
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.
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.
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:
So the output result is: Promise {
The execution result in the browser is as follows:
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:
六个阶段分别是:
事件循环中,每当进入某一个阶段,都会从该阶段对应的回调队列中取出函数去执行。当队列为空或者执行的回调函数数量到达系统设定的阈值,该阶段就会终止,然后检查NextTick队列和微任务队列,将其清空,之后进入下一个阶段。
这里面比较关键的是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,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); });
继续分析:
因此最终输出是: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!