Node之Event loop
Posted 架构师日刊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Node之Event loop相关的知识,希望对你有一定的参考价值。
1、长期为你提供最优质的学习资源!
2、给你解决技术问题!
4、每周1、3、5送纸质书籍免费送给大家,每年至少送书800本书!
5、为大家推荐靠谱的就业单位!
请注意!我上面说的5点全部都是免费的!全网你应该找不到第二家吧!
当然,大家在我私人微信上问我问题,仅限回答web前端、java相关的。
---------------------------
好了,接下来开始今天的技术分享!上次老师跟大家分享了Node之简介的知识,今天跟大家分享下Node之Event loop的知识。
1 Event loop是什么?
Event loop 允许node.js执行非阻塞I/O操作(尽管JS是单线程的),也就是在相应情况下,尽可能的将任务交给系统内核。
多数内核是多线程的,可以同时处理多个任务。当其中一个任务完成时,相应的callback被插入到轮询队列中,最终被执行。
2 事件循环
事件循环包含几个阶段,相应的阶段做相应的事。
初始化: Node.js启动后,会进行一些初始化
初始化Event loop
处理目标脚本
然后进入事件循环
每个阶段,都有其FIFO队列,用来执行回调函数。
每个阶段都是特殊的。
当进行到该阶段时,会执行该阶段特有的操作,然后执行该阶段队列中的回调。
当队列空,或者达到执行次数限制,事件循环进行下阶段。
循环往复。
timers:执行setTimeout()和setInterval安排的回调
I/O callbacks: 执行几乎所有异常的close回调,由timer和setImmediate执行的回调。
idle,prepare: 只用于内部
poll : 获取新的I/O事件,node在该阶段会适当的阻塞
check : setImmediate的回调被调用
close callbacks: e.g socket.on(‘close’,…);
在每次运行事件循环之间,node.j检查是否有正在等待的异步i/o调用、timers等。如果没有,就清除并结束(退出程序),例如:执行一个程序,仅有一句话(var a= ‘hello’;),处理完目标代码后,不会进入evetloop,而是直接结束程序。
每个阶段
Timers:定时器可以设置回调函数在指定时间后运行。这个回调函数会在能够被调度后,尽可能快的运行。操作系统的调度,或其他回调数的运行,可能会延迟该回调函数的运行。**通常,poll阶段控制定时器的运行。
当事件循环进入poll阶段,根据该阶段队列内容执行:
执行队列中的回调函数
当队列中没有回调函数时,且定时器设置时间已过
回到timers 阶段,执行相应的回调函数
**为了防止poll阶段过长,libuv根据为不同系统设置了poll阶段的最长事件。
I/O callbacks:该阶段执行一些如TCP错误之类的系统操作的会ID回调。
Poll(轮询):
两个主要功能
执行定时器设置并到期的回调函数,然后
处理poll队列中的事件
工作机制:当没有timers被调度,分两种情况
如果poll队列不为空,会挨个执行队列里的callback,直到队列为空,或达到系统限制
如果poll队列为空,分两种情况:
1,如果执行了setImmediate(),eventloop会结束poll阶段,进入到check阶段执行 ,
2,如果没有执行setImmediate(),eventloop会等待callback进入队列
一旦poll队列为空,evetloop会检查timers,如果计时已到,event loop 会回到 timers 阶段,执行相应的回调函数.
check阶段
poll阶段变为空闲、等待状态时,一旦调用setImmediate(),eventloop会进入check 阶段,而不是在poll阶段等待。
close callbacks阶段
例如:socket或句柄关闭,close事件会触发这个阶段。或者通过process.nextTick()触发
4 总结
Node.js事件循环有实际上7、8个阶段,但我们关注-node实际使用的,就是前面说的几个。每个阶段都有自己的队列。本阶段执行完成后,执行下一个阶段。循环顺序不是完全固定的,很多阶段都是由外部事件触发的。
重要的三阶段:
timers,定时器阶段:
执行定时任务(setTimeOut(), setInterval())
poll 轮询阶段:
处理到期的定时器任务,然后(因为最开始阶段队列为空,一旦队列为空,就会检查是否有到期的定时器任务)
处理队列任务,直到队列空,或达到上限
如果队列为空:如果setImmediate,终止轮询阶段,进入检查阶段执行。如果没setImmediate,查看有没有定时器任务到期,有的话就到timers阶段,执行回调函数.
check 检查阶段
轮询阶段空闲,且有setImmediate的时候,进入检查阶段
不重要二阶段
I/O callbacks阶段:处理I/O异常错误
close callbacks阶段: 处理各种close事件回调
const fs = require('fs');
setTimeout(function(){
console.log('ff');
},0);
function func(cb) {
fs.readFile('xxx.js',cb);
}
func( () => {
console.log('a');
})
参考:https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#why-would-that-be-allowed
今天就分享这么多,关于Node之 Event loop,你学会了多少?欢迎在留言区评论,对于有价值的留言,我们都会一一回复的。如果觉得文章对你有一丢丢帮助,请点右下角【在看】,让更多人看到该文章。
全网应该只有我能做到了吧!有技术问题可以在微信上问我!(如下图)
以上是关于Node之Event loop的主要内容,如果未能解决你的问题,请参考以下文章
[未解决问题记录]python asyncio+aiohttp出现Exception ignored:RuntimeError('Event loop is closed')(代码片段