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 相关文章推荐
JavaScript prototype对象的属性说明
Mar 13 Javascript
ASP中Sub和Function的区别说明
Aug 30 Javascript
jQuery手机浏览器中拖拽动作的艰难性分析
Feb 04 Javascript
JavaScript动态改变表格单元格内容的方法
Mar 30 Javascript
基于jQuery实现带动画效果超炫酷的弹出对话框(附源码下载)
Feb 22 Javascript
JavaScript基础语法之js表达式
Jun 07 Javascript
AngularJS入门教程之Scope(作用域)
Jul 27 Javascript
浅谈JS中的反柯里化( uncurrying)
Aug 17 Javascript
jquery+ajaxform+springboot控件实现数据更新功能
Jan 22 jQuery
VUE解决微信签名及SPA微信invalid signature问题(完美处理)
Mar 29 Javascript
layui文件上传控件带更改后数据传值的方法
Sep 23 Javascript
antd的select下拉框因为数据量太大造成卡顿的解决方式
Oct 31 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
Laravel框架运行出错提示RuntimeException No application encryption key has been specified.解决方法
2019/04/02 PHP
Laravel 框架基于自带的用户系统实现登录注册及错误处理功能分析
2020/04/14 PHP
静态页面下用javascript操作ACCESS数据库(读增改删)的代码
2007/05/14 Javascript
XML的代替者----JSON
2007/07/21 Javascript
基于Jquery的温度计动画效果
2010/06/18 Javascript
jquery中this的使用说明
2010/09/06 Javascript
纯js实现背景图片切换效果代码
2010/11/14 Javascript
javascript中的throttle和debounce浅析
2014/06/06 Javascript
jQuery实现购物车多物品数量的加减+总价计算
2014/06/06 Javascript
JS基于面向对象实现的拖拽库实例
2015/09/24 Javascript
JS检测移动端横竖屏的代码
2016/05/30 Javascript
AngularJs Understanding the Controller Component
2016/09/02 Javascript
浅谈jquery高级方法描述与应用
2016/10/04 Javascript
vue2实现移动端上传、预览、压缩图片解决拍照旋转问题
2017/04/13 Javascript
javascript修改浏览器title方法 JS动态修改浏览器标题
2017/11/30 Javascript
实例讲解JavaScript截取字符串
2018/11/30 Javascript
Angular使用ControlValueAccessor创建自定义表单控件
2019/03/08 Javascript
vue2配置scss的方法步骤
2019/06/06 Javascript
ionic2.0双击返回键退出应用
2019/09/17 Javascript
在vue-cli中引入lodash.js并使用详解
2019/11/13 Javascript
国内常用的js类库大全(CDN公共库)
2020/06/24 Javascript
[01:02:09]Liquid vs TNC 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.21
2020/07/19 DOTA
举例讲解Python中的算数运算符的用法
2015/05/13 Python
Python使用正则表达式抓取网页图片的方法示例
2017/04/21 Python
Python人脸识别初探
2017/12/21 Python
使用Python处理BAM的方法
2018/09/28 Python
Python实现钉钉发送报警消息的方法
2019/02/20 Python
pandas DataFrame 警告(SettingWithCopyWarning)的解决
2019/07/23 Python
CSS3的column-fill属性对齐列内容高度的用法详解
2016/07/01 HTML / CSS
调用HTML5的Canvas API绘制图形的快速入门指南
2016/06/17 HTML / CSS
日本运动品牌美津浓官方购物网站:MIZUNO SHOP
2016/08/21 全球购物
招商经理岗位职责
2013/11/16 职场文书
健康家庭事迹材料
2014/05/02 职场文书
学校欢迎标语
2014/06/18 职场文书
故意杀人罪辩护词
2015/05/21 职场文书
在职证明书模板
2015/06/15 职场文书