Node.js Event Loop各阶段讲解


Posted in Javascript onMarch 08, 2019

Event Loop阶段描述图

Node.js Event Loop各阶段讲解

timers

timer阶段处理setTimeout于setInterval回调,开始处理的时机与poll阶段有关联。

pending callbacks

该阶段执行某些系统操作的回调,比如TCP套接字在连接时收到ECONNREFUSED。

网上有一些将该阶段称为I/O callbacks的文章都是过时错误的,具体可以移步Node.js官方库下面的这个issue: #1118。

idle, prepare

内部使用,忽略。

poll

poll是一个核心阶段,等新I/O事件的触发,以及执行I/O相关回调。Node.js中出现异步的绝大部分情况都是I/O操作,它们的回调基本都在这个阶段被执行。

poll阶段主要做两件事:

  • 计算需要为新的的I/O事件等待多久

当进入poll阶段,如果队列为空且不存在setImmediate与就绪的timer,Node.js会在这里block一定的时间等待新的I/O事件到来,然后立即执行其回调。这种情况具体block等待多久是不具体的,但如果在block一定时间后仍没有新到达的I/O事件,可以肯定循环依旧会进入check阶段或者回到timer阶段。

  • 处理该阶段队列中的事件

当进入poll阶段,如果队列不为空且没有就绪的timer,Node.js会在这里执行队列中的callback直到队列为空或者执行的callback数达到系统设定的某个值。随后Node.js检查是否存在预设的setImmediate,存在话就进入check阶段,否则开始检查timer就绪情况选择回到timer阶段或者进入check阶段。

对于poll阶段,通过阅读官方的文档有些细节也没弄清楚,用伪代码表示出来:

enter pool phase:
if (has timer scheduled) {
  // 官方没有提到这种情况会做什么
}
else {
  if (isEmpty(queue)) {
    if (has(setImmediate)) {
      // 进入check阶段
    }
    else if (!isEmpty(timer)) {
      // 回到timer阶段
    }
    else {
      // 等待新的I/O事件
      // 新的I/O事件触发回调立即执行,执行完成之后的逻辑不清楚
    }
    // 目前看来只有存在setImmediate时才会进入check阶段,这肯定不合理
  }
  if (!isEmpty(queue)) {
    let result = execute(queue);
    if (result === 'queue is empty') {
      // 官方没讲后续逻辑
      // 猜测是回到队列为空的处理逻辑中
    }
    if (result === 'reached hard limit') {
      // 官方没有解释这里的后续逻辑
      // 也许与queue is empty一样对待
    }
  }
}

疑惑重点是从poll阶段出来的时机以及去向不是非常明确,但以我目前的水平和精力只能到此为止。

check

当poll阶段执行完成会进入到check阶段执行,该阶段的执行内容是所有setImmediate回调。

close callbacks

socket的异常关闭,'close'事件的回调会在该阶段执行。

process.nextTick

process.nextTick经常被用来做异步调用,但它并不属于事件循环的内容,process.nextTick中的回调被放在nextTickQueue中等待“当前操作”完成后被立即处理,与事件循环中的阶段没有联系,当前操作的原文定义是:“An operation is defined as a transition from the underlying C/C++ handler, and handling the JavaScript that needs to be executed.”,指的是在一段Javascript代码执行完切换到C/C++层时会处理nextTickQueue。

文章提到了一个特例是Deduplication,这是Node.js内部一个优化特性,当在timer和check阶段,同时有多个需要执行的回调时,切换只会发生一次,所以nextTick回调执行在这种情况下看似有所延后。

代码示例:

setImmediate(() => {
  console.log('1');
  process.nextTick(() => console.log('2'));
});
setImmediate(() => {
  console.log('3');
  process.nextTick(() => console.log('4'));
});

存在两个setImmediate,进入check阶段后需要在执行所有setImmediate的回调代码后才会产生切换,从而执行nextTick回调,因此上面代码的运行结果是:“1 3 2 4”,除上述场景外,nextTick都会先于setImmediate执行。

总结

因为Node.js的Event Loop我看了有那么2、3回,但经常忘,所以这次记录下来,做个备忘。由于太多知识容易忘记,又发现写文章的一个优点:“帮助记忆便于复习”。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。如果你想了解更多相关内容请查看下面相关链接

Javascript 相关文章推荐
js不是基础的基础
Dec 24 Javascript
javascript dom 操作详解 js加强
Jul 13 Javascript
js动态添加onload、onresize、onscroll事件(另类方法)
Dec 26 Javascript
Ext JS动态加载JavaScript创建窗体的方法
Jun 23 Javascript
详解bootstrap的modal-remote两种加载方式【强化】
Jan 27 Javascript
Angular多选、全选、批量选择操作实例代码
Mar 10 Javascript
vue2.x 父组件监听子组件事件并传回信息的方法
Jul 17 Javascript
Node.js如何实现注册邮箱激活功能 (常见)
Jul 23 Javascript
JS继承与闭包及JS实现继承的三种方式
Oct 15 Javascript
详解基于vue-cli3.0如何构建功能完善的前端架子
Oct 09 Javascript
解决ie11 SCRIPT5011:不能执行已释放Script的代码问题
May 05 Javascript
微信小程序iOS下拉白屏晃动问题解决方案
Oct 12 Javascript
vue基础之data存储数据及v-for循环用法示例
Mar 08 #Javascript
vue.js使用v-model实现表单元素(input) 双向数据绑定功能示例
Mar 08 #Javascript
JavaScript解析机制与闭包原理实例详解
Mar 08 #Javascript
零基础之Node.js搭建API服务器的详解
Mar 08 #Javascript
详解vue项目中使用token的身份验证的简单实践
Mar 08 #Javascript
Javascript之高级数组API的使用实例
Mar 08 #Javascript
详解基于vue-cli3快速发布一个fullpage组件
Mar 08 #Javascript
You might like
一个目录遍历函数
2006/10/09 PHP
PHP 文件上传功能实现代码
2009/06/24 PHP
在PHP中实现Javascript的escape()函数代码
2010/08/08 PHP
CentOS6.5 编译安装lnmp环境
2014/12/21 PHP
PHP中error_log()函数的使用方法
2015/01/20 PHP
PHP结合jQuery实现找回密码
2015/07/22 PHP
jQuery+jqmodal弹出窗口实现代码分明
2010/06/14 Javascript
Jquery中对数组的操作代码
2011/08/12 Javascript
jquery 卷帘效果实现代码(不同方向)
2013/02/05 Javascript
js操作checkbox遇到的问题解决
2013/06/29 Javascript
java、javascript实现附件下载示例
2014/08/14 Javascript
JavaScript编程中布尔对象的基本使用
2015/10/25 Javascript
JavaScript ES6的新特性使用新方法定义Class
2016/06/28 Javascript
JS实现保留n位小数的四舍五入问题示例
2016/08/03 Javascript
Javascript 制作图形验证码实例详解
2016/12/22 Javascript
Vue响应式添加、修改数组和对象的值
2017/03/20 Javascript
Django与Vue语法的冲突问题完美解决方法
2017/12/14 Javascript
angular中如何绑定iframe中src的方法
2019/02/01 Javascript
在微信小程序中使用vant的方法
2019/06/07 Javascript
ES6顶层对象、global对象实例分析
2019/06/14 Javascript
[38:54]完美世界DOTA2联赛PWL S2 Rebirth vs LBZS 第一场 11.28
2020/12/01 DOTA
python 实现对文件夹内的文件排序编号
2018/04/12 Python
Django框架搭建的简易图书信息网站案例
2019/05/25 Python
python爬虫 2019中国好声音评论爬取过程解析
2019/08/26 Python
pandas将多个dataframe以多个sheet的形式保存到一个excel文件中
2019/10/10 Python
tensorflow 实现打印pb模型的所有节点
2020/01/23 Python
python tkiner实现 一个小小的图片翻页功能的示例代码
2020/06/24 Python
python爬虫利用selenium实现自动翻页爬取某鱼数据的思路详解
2020/12/22 Python
html Table 表头固定的实现
2019/01/22 HTML / CSS
工商管理应届生求职信
2013/10/07 职场文书
培训主管的职业生涯规划
2014/03/06 职场文书
初中升旗仪式演讲稿
2014/05/08 职场文书
长城导游词400字
2015/01/30 职场文书
简单的辞职信怎么写
2015/02/28 职场文书
汽车4S店销售经理岗位职责
2015/04/02 职场文书
JavaScript继承的三种方法实例
2021/05/12 Javascript