DAY7: Node 的事件循环 (Event loop)

今日要介绍Node事件循环的概念,前面文章一直提到Node和JavaScipt虽然拖不了太大的关系,但其中与JavaScript的事件循环又有些不一样。

何谓事件循环(Event loop)?

在JavaScript是单线程,需要由异步加上回调的模式,来避免阻塞,而事件循环是在浏览器中实现的。
在Node中也是单线程,但能支持高并发,就是靠事件循环,而事件循环是由底层的Libuv所实现。

下图是Node事件循环流程图:https://ithelp.ithome.com.tw/upload/images/20210919/20140244MI6tRFizTu.jpg

总共有六个不同阶段,每个阶段都有自己的回调函数,处理着不同的事件。
timers: 用来执行处理setTimeOut()setInterval()的回调
I/O callbacks: 执行处理系统错误的回调。
poll: 不断来回检视是否有新的I/O事件发生,这里也是也可能产生阻塞的阶段。
idle,prepare: 仅於node内部使用,不须理会。
Check: 处理setImmediate() 的回调。
Close callbacks: c lose在此发出事件。

可参考官网资料,解释得更详细:
https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/

充分了解後,实际操作例子:

//事件循环
var fs=require('fs');
var timeoutScheduled=Date.now();
 setTimeout(function()
 {
   var delay=Date.now()-timeoutScheduled;
   console.log('A total of '+delay+' seconds was wasted after execution!By Nicole!!');
 },100);

 fs.readFile('/path/to/file',function(err,data)
 {
   var startCallback=Date.now();
   while (Date.now()-startCallback<10){//用while回圈阻塞10毫秒
     ;//表示不做任何动作
   }
 });

程序码改编官方网站与参考书 李锴<新时期的Node.js入门>。
执行结果:
https://ithelp.ithome.com.tw/upload/images/20210919/20140244poLNW1daEw.jpg

利用上面这段程序码来解释事件循环(配合Node事件循环流程图)。
假设读取文件需要95毫秒。
当开始执行事件循环後,timers阶段到2000毫秒後才会发生,接着到poll阶段,检查有没有新的事件,而目前尚未有新事件发生,因上面没有定义setImmediate(),所以事件循环就一直在poll阶段无法进入到check阶段。
到了95毫秒後readFile读取完毕後,产生新事件,而poll阶段接收到後,事件循环开始执行回调函数,而readFile回调只是阻塞的了10毫秒。而总阻塞的时间是95+10=105(可能多一点也可能少一点),但都会大於100毫秒。

多执行几次出来的秒数也不一定一样,但都大於100毫秒。

https://ithelp.ithome.com.tw/upload/images/20210919/20140244UBBVyqS9Ql.jpg

可以做个小实验修改上面的豪秒数,出来结果的时间都一定大於你设定的毫秒数。

补充:
上面一开始有提到Node的高并发,有跟并发字面上很相似的并行,我在理解的时候,也容易混淆,下面以生活化的例子做解释。
大家都有去买速食店的经验吧!假设目前人手短缺,只有开放一个柜台,现在分成两排队伍,
第一排是现场点餐的,第二排是拿餐的。那麽……

并发:

为了两排人的公平起见,第一排的一个人先前往柜台点餐,完毕後,接着第二排的一个人在前往柜台取餐!
也就是说柜台一次要做两件不同的事,要点餐又要取餐,而我两排的队伍皆有在移动(只是移动的速度极慢),可以想更简单一点,就是压榨柜台员工要身兼多职,还要确保不同队伍都有被处理。

并行:

现在人手变多了!我再开放一个柜台(现在共有两个柜台在运作),一个柜台负责第一排,另一个柜台负责第二排。如此一来,流动率就提高,效率就高了!

总结:
今天的事件循环感觉有点难,自己也理解了很久…,若有解释得比较简陋的部分或是有错误的部分,再请指点。
参考资料:
这部影片包含了JavaScript的事件循环介绍,个人觉得解说得很仔细。
https://www.youtube.com/watch?v=8aGhZQkoFbQ
Node官网事件循环解说:
https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/


<<:  Angular Reactive Forms 自订表单验证器

>>:  Day03 - 【入门篇】浅谈身份验证与授权(1)

Day 06 Use automated machine learning in Azure Machine Learning

To use Azure Machine Learning Create an Azure Mach...

Day-12 Ruby里Block,Proc,Lambda差别?

大家常常搞混的三兄弟,我们一起来了解他们! Block 是程序码区块,不能单独存活,要接在方法(m...

用React刻自己的投资Dashboard Day14 - 解决重复发送API请求的问题

tags: 2021铁人赛 React 之前刚开始设计call api取得资料的时间点是在Card元...

#25-让长条图一条条动起来~大数据时代!入手 D3.js~

自己做行销的时候,很喜欢玩数据, 数据可以打破一些先入为主的想法、 也可以给我们更全面的视角、或是新...

Day 23. Server Side Rendering

Server side rendering 在一般的 Vue 专案里可能会有一个App.vue,里面...