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 相关文章推荐
jQuery boxy弹出层插件中文演示及使用讲解
Feb 24 Javascript
常用js字符串判断方法整理
Oct 18 Javascript
jquery实现键盘左右翻页特效
Apr 30 Javascript
Express实现前端后端通信上传图片之存储数据库(mysql)傻瓜式教程(二)
Dec 10 Javascript
Bootstrap~多级导航(级联导航)的实现效果【附代码】
Mar 08 Javascript
vue使用element-ui的el-input监听不了回车事件的解决方法
Jan 12 Javascript
Vue中使用clipboard实现复制功能
Sep 05 Javascript
微信小程序实现星级评价效果
Dec 28 Javascript
Vue模板语法中数据绑定的实例代码
May 17 Javascript
三步实现ionic3点击退出app程序
Sep 17 Javascript
js实现提交前对列表数据的增删改查
Jan 16 Javascript
pnpm对npm及yarn降维打击详解
Aug 05 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
创建数据库php代码 用PHP写出自己的BLOG系统
2010/04/12 PHP
解析PHP中如何将数组变量写入文件
2013/06/06 PHP
Window下PHP三种运行方式图文详解
2013/06/11 PHP
php实现的简单日志写入函数
2015/03/31 PHP
PHPMAILER实现PHP发邮件功能
2018/04/18 PHP
让Laravel API永远返回JSON格式响应的方法示例
2018/09/05 PHP
使用Jquery来实现可以输入值的下拉选单 雏型
2011/12/06 Javascript
javascript重复绑定事件造成的后果说明
2013/03/02 Javascript
JavaScript代码简单实现求杨辉三角给定行的最大值
2013/10/29 Javascript
checkbox勾选判断代码分析
2014/06/11 Javascript
不使用script导入js文件的几种方法
2016/10/27 Javascript
利用JS判断字符串是否含有数字与特殊字符的方法小结
2016/11/25 Javascript
解析Javascript单例模式概念与实例
2016/12/05 Javascript
React组件的三种写法总结
2017/01/12 Javascript
js 调用百度分享功能
2017/02/27 Javascript
vue中element-ui表格缩略图悬浮放大功能的实例代码
2018/06/26 Javascript
JS高阶函数原理与用法实例分析
2019/01/15 Javascript
[27:39]Ti4 循环赛第二日 LGD vs Fnatic
2014/07/11 DOTA
改进Django中的表单的简单方法
2015/07/17 Python
解决pyqt中ui编译成窗体.py中文乱码的问题
2016/12/23 Python
Python安装Numpy和matplotlib的方法(推荐)
2017/11/02 Python
Python实现句子翻译功能
2017/11/14 Python
Django给admin添加Action的步骤详解
2019/05/01 Python
pytorch方法测试详解——归一化(BatchNorm2d)
2020/01/15 Python
解决TensorFlow模型恢复报错的问题
2020/02/06 Python
sklearn和keras的数据切分与交叉验证的实例详解
2020/06/19 Python
Python+Opencv实现把图片、视频互转的示例
2020/12/17 Python
戴森西班牙官网:Dyson西班牙
2020/02/04 全球购物
结婚邀请函范文
2014/01/14 职场文书
大学生活动策划方案
2014/02/10 职场文书
班主任新年寄语
2014/04/04 职场文书
老公给老婆的保证书
2014/04/28 职场文书
品牌推广策划方案
2014/05/28 职场文书
教师节学生演讲稿
2014/09/03 职场文书
学雷锋倡议书
2015/01/19 职场文书
2016大学自主招生推荐信范文
2015/03/23 职场文书