这次给大家带来node.js的event loop详解,使用node.js的event loop注意事项有哪些,下面就是实战案例,一起来看一下。
node.js也是单线程的event loop,但是它的运行机制不同于浏览器环境。
请看下面的示意图
根据上图,node.js的运行机制如下。
(1)v8引擎解析javascript脚本。
(2)解析后的代码,调用node api。
(3)libuv库负责node api的执行。它将不同的任务分配给不同的线程,形成一个event loop(事件循环),以异步的方式将任务的执行结果返回给v8引擎。
(4)v8引擎再将结果返回给用户。
除了settimeout和setinterval这两个方法,node.js还提供了另外两个与任务队列有关的方法:process.nexttick和setimmediate。它们可以帮助我们加深对任务队列的理解。
process.nexttick方法可以在当前执行栈的尾部----下一次event loop(主线程读取任务队列)之前----触发回调函数。也就是说,它指定的任务总是发生在所有异步任务之前。setimmediate方法则是在当前任务队列的尾部添加事件,也就是说,它指定的任务总是在下一次event loop时执行,这与settimeout(fn, 0)很像。请看下面的例子(via stackoverflow)。
process.nexttick(function a() {
console.log(1);
process.nexttick(function b(){console.log(2);});});settimeout(function timeout() {
console.log('timeout fired');}, 0)// 1// 2// timeout fired
上面代码中,由于process.nexttick方法指定的回调函数,总是在当前"执行栈"的尾部触发,所以不仅函数a比settimeout指定的回调函数timeout先执行,而且函数b也比timeout先执行。这说明,如果有多个process.nexttick语句(不管它们是否嵌套),将全部在当前"执行栈"执行。
现在,再看setimmediate。
setimmediate(function a() {
console.log(1);
setimmediate(function b(){console.log(2);});});settimeout(function timeout() {
console.log('timeout fired');}, 0);
上面代码中,setimmediate与settimeout(fn,0)各自添加了一个回调函数a和timeout,都是在下一次event loop触发。那么,哪个回调函数先执行呢?答案是不确定。运行结果可能是1--timeout fired--2,也可能是timeout fired--1--2。
令人困惑的是,node.js文档中称,setimmediate指定的回调函数,总是排在settimeout前面。实际上,这种情况只发生在递归调用的时候。
setimmediate(function (){
setimmediate(function a() {
console.log(1);
setimmediate(function b(){console.log(2);});
});
settimeout(function timeout() {
console.log('timeout fired');
}, 0);});// 1// timeout fired// 2
上面代码中,setimmediate和settimeout被封装在一个setimmediate里面,它的运行结果总是1--timeout fired--2,这时函数a一定在timeout前面触发。至于2排在timeout fired的后面(即函数b在timeout后面触发),是因为setimmediate总是将事件注册到下一轮event loop,所以函数a和timeout是在同一轮loop执行,而函数b在下一轮loop执行。
我们由此得到了process.nexttick和setimmediate的一个重要区别:多个process.nexttick语句总是在当前"执行栈"一次执行完,多个setimmediate可能则需要多次loop才能执行完。事实上,这正是node.js 10.0版添加setimmediate方法的原因,否则像下面这样的递归调用process.nexttick,将会没完没了,主线程根本不会去读取"事件队列"!
process.nexttick(function foo() {
process.nexttick(foo);});
事实上,现在要是你写出递归的process.nexttick,node.js会抛出一个警告,要求你改成setimmediate。
另外,由于process.nexttick指定的回调函数是在本次事件循环触发,而setimmediate指定的是在下次事件循环触发,所以很显然,前者总是比后者发生得早,而且执行效率也高(因为不用检查任务队列)。
相信看了本文案例你已经掌握了方法,更多精彩请关注其它相关文章!
推荐阅读:
javascript的定时器详解
javascript运行机制之事件和回调函数
浏览器的多线程机制详解
关于js中类型转换的一些小问题
以上就是node.js的event loop详解的详细内容。