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 中关于CSS操作部分使用说明
Jun 10 Javascript
jquery怎样实现ajax联动框(二)
Mar 08 Javascript
ExtJs动态生成treepanel的Json格式
Jul 19 Javascript
JS+CSS实现美化的下拉列表框效果
Aug 11 Javascript
js实现文本框宽度自适应文本宽度的方法
Aug 13 Javascript
js中利用tagname和id获取元素的方法
Jan 03 Javascript
快速使用Bootstrap搭建传送带
May 06 Javascript
vue实现全选、反选功能
Nov 17 Javascript
js实现窗口全屏示例详解
Sep 17 Javascript
axios 实现post请求时把对象obj数据转为formdata
Oct 31 Javascript
BootstrapValidator验证用户名已存在(ajax)
Nov 08 Javascript
如何手动实现一个 JavaScript 模块执行器
Oct 16 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
探讨:array2xml和xml2array以及xml与array的互相转化
2013/06/24 PHP
php加密算法之实现可逆加密算法和解密分享
2014/01/21 PHP
php使用正则过滤js脚本代码实例
2014/05/10 PHP
浅析PHP echo 和 print 语句
2020/06/30 PHP
jQuery对象[0]是什么含义?
2010/07/31 Javascript
JQuery中操作Css样式的方法
2014/02/12 Javascript
JavaScript中的变量作用域介绍
2014/12/31 Javascript
用window.onerror捕获并上报Js错误的方法
2016/01/27 Javascript
js实现动态创建的元素绑定事件
2016/07/19 Javascript
javascript 判断页面访问方式电脑或者移动端
2016/09/19 Javascript
JS的函数调用栈stack size的计算方法
2018/06/24 Javascript
JavaScript实现的前端AES加密解密功能【基于CryptoJS】
2018/08/28 Javascript
JS使用数组实现的队列功能示例
2019/03/04 Javascript
[02:54]DOTA2英雄基础教程 暗影牧师戴泽
2013/12/05 DOTA
Python程序员面试题 你必须提前准备!(答案及解析)
2018/01/23 Python
用Python3创建httpServer的简单方法
2018/06/04 Python
python批量修改文件夹及其子文件夹下的文件内容
2019/03/15 Python
Python后台开发Django的教程详解(启动)
2019/04/08 Python
使用TensorFlow-Slim进行图像分类的实现
2019/12/31 Python
python enumerate内置函数用法总结
2020/01/07 Python
python实现高斯投影正反算方式
2020/01/17 Python
关于Python Tkinter Button控件command传参问题的解决方式
2020/03/04 Python
Python调用接口合并Excel表代码实例
2020/03/31 Python
python中什么是面向对象
2020/06/11 Python
Matplotlib animation模块实现动态图
2021/02/25 Python
canvas生成带二维码海报的踩坑记录
2019/09/11 HTML / CSS
C/C++有关内存的思考题
2015/12/04 面试题
SQL Server面试题
2016/10/17 面试题
骨干教师培训制度
2014/01/13 职场文书
视光学专业自荐信
2014/06/24 职场文书
领导干部贪图享乐整改措施
2014/09/21 职场文书
公司党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
三方股东合作协议书范本
2014/09/28 职场文书
2014年食品安全工作总结
2014/12/04 职场文书
Python数据分析之绘图和可视化详解
2021/06/02 Python
分享一些Java的常用工具
2021/06/11 Java/Android