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 进阶篇3 Ajax 、JSON、 Prototype介绍
Mar 14 Javascript
js跑马灯代码(自写)
Apr 17 Javascript
jQuery+css3动画属性制作猎豹浏览器宽屏banner焦点图
Mar 16 Javascript
简介JavaScript中POSITIVE_INFINITY值的使用
Jun 05 Javascript
JavaScript的==运算详解
Jul 20 Javascript
Bootstrap中的fileinput 多图片上传及编辑功能
Sep 05 Javascript
Ionic + Angular.js实现图片轮播的方法示例
May 21 Javascript
基于vue和react的spa进行按需加载的实现方法
Sep 29 Javascript
layui 表格操作列按钮动态显示的实现方法
Sep 06 Javascript
原生js滑动轮播封装
Jul 31 Javascript
vue的$http的get请求要加上params操作
Nov 12 Javascript
js实现有趣的倒计时效果
Jan 19 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中使用array函数新建一个数组
2015/11/19 PHP
WordPress中查询文章的循环Loop结构及用法分析
2015/12/17 PHP
PHP常用字符串输出方法分析(echo,print,printf及sprintf)
2021/03/09 PHP
Js+Dhtml:WEB程序员简易开发工具包(预先体验版)
2006/11/07 Javascript
jquery自动完成插件(autocomplete)应用之PHP版
2009/12/15 Javascript
jQuery自动切换/点击切换选项卡效果的小例子
2013/08/12 Javascript
jquery.cookie() 方法的使用(读取、写入、删除)
2013/12/05 Javascript
Select标签下拉列表二级联动级联实例代码
2014/02/07 Javascript
jQuery 计算iframe 窗口大小的方法
2014/05/13 Javascript
做web开发 先学JavaScript
2014/12/12 Javascript
基于jquery实现在线选座订座之影院篇
2015/08/24 Javascript
JS操作XML实例总结(加载与解析XML文件、字符串)
2015/12/08 Javascript
整理关于Bootstrap模态弹出框的慕课笔记
2017/03/29 Javascript
JavaScript 下载svg图片为png格式
2018/06/21 Javascript
vue+Element-ui实现分页效果实例代码详解
2018/12/10 Javascript
vue组件之间通信方式实例总结【8种方式】
2019/02/22 Javascript
Vue可自定义tab组件用法实例
2019/10/24 Javascript
9种方法优化jQuery代码详解
2020/02/04 jQuery
[00:33]2016完美“圣”典风云人物:Sccc宣传片
2016/12/03 DOTA
[34:08]2018DOTA2亚洲邀请赛3月29日 小组赛B组 VP VS EG
2018/03/30 DOTA
Python通过解析网页实现看报程序的方法
2014/08/04 Python
Python函数式编程指南(一):函数式编程概述
2015/06/24 Python
python下os模块强大的重命名方法renames详解
2017/03/07 Python
Python 转义字符详细介绍
2017/03/21 Python
Python 查看文件的编码格式方法
2017/12/21 Python
python+opencv轮廓检测代码解析
2018/01/05 Python
python3爬虫获取html内容及各属性值的方法
2018/12/17 Python
Django中ORM外键和表的关系详解
2019/05/20 Python
python发送多人邮件没有展示收件人问题的解决方法
2019/06/21 Python
python多线程+代理池爬取天天基金网、股票数据过程解析
2019/08/13 Python
在Python中通过threshold创建mask方式
2020/02/19 Python
浅谈pandas dataframe对除数是零的处理
2020/07/20 Python
Lulu & Georgia官方网站:购买地毯、家具、抱枕、壁纸、床上用品等
2018/03/19 全球购物
爱尔兰电子产品购物网站:Komplett.ie
2018/04/04 全球购物
小学生暑假生活总结
2015/07/13 职场文书
教师节主题班会方案
2015/08/17 职场文书