javascript - 为什么 Node.js setImmediate 在 I/O 回调之后执行?

标签 javascript node.js asynchronous event-loop setimmediate

作为新成员(member),我无法对主题发表评论,这就是我必须创建一个新主题的原因。但这样我就可以澄清问题了,希望大家能够帮助我。

我读了很多关于 Node.js 事件循环的文章。我根据以下 Material 形成了对它的理解:

Node.js Event Loop
What the heck is the event loop anyway?
Why setImmediate() execute before fs.readFile() in Nodejs Event Loop's works?

(请随时推荐其他内容丰富且准确的 Material )

尤其是第三个链接,让我有了更好的理解。但请记住这一点,我无法理解以下代码的事件循环行为:

var fs = require('fs');
var pos = 0;

fs.stat(__filename, function() {
 console.log(++pos + " FIRST STAT");
});

fs.stat(__filename, function() {
 console.log(++pos + " LAST STAT");
});

setImmediate(function() {
 console.log(++pos + " IMMEDIATE")
})

console.log(++pos + "LOGGER");

令人惊讶的是,对我来说输出如下:

LOGGER  
FIRST STAT  
LAST STAT  
IMMEDIATE

screenshot of my terminal, showing output as well as node version
screenshot of output from online code compiler rextester.com

保持事件循环 Diagram考虑到,我想流程应该如下:

  1. 解释器首先启动两个统计操作。
  2. 解释器将 setImmedate 回调(事件)加入到 setImmedate 队列中
  3. 调用堆栈记录记录器
  4. I/O 轮询阶段之前的所有事件队列都是空的,因此事件循环 (EL) 继续
  5. 在 I/O 轮询阶段,EL 收集事件并将 fs.stat 回调排入“运行已完成的 I/O 处理程序”阶段
  6. EL 检查 Check 阶段,并运行 setImmediate 回调
  7. 本轮EL结束,第二轮开始
  8. 在“运行已完成的 I/O 处理程序”中,EL 运行两个回调(它们的顺序是不确定的)

问题 1:我的分析/预测哪部分是错误的?

问题 2:事件循环在什么时候开始工作?它是从应用程序的开头(即第 1 阶段)开始的吗?或者一旦解释器读取整个代码,所有同步任务都在调用堆栈中完成,并且调用堆栈需要更多任务,即在阶段 3-4 之间,它就开始吗?

提前致谢,

最佳答案

setImmediate = 执行而不等待任何 I/O

https://nodejs.org/docs/v8.9.3/api/timers.html#timers_setimmediate_callback_args说:

Schedules the "immediate" execution of the callback after I/O events' callbacks. Returns an Immediate for use with clearImmed

步骤:

  1. 第一个统计数据的回调在 I/O 队列中排队
  2. 最后统计数据的回调已在 I/O 队列中排队
  3. 立即回调在立即队列中排队
  4. 记录器
  5. 如果 I/O 操作(1 和 2 中)完成,则 1 和/或 2 中的回调将被标记为准备执行
  6. 逐个执行就绪回调(第一个计时器,然后 I/O,最后立即执行)。在你的情况下:
    1. 第一个统计数据
    2. 最后统计数据
    3. 记录器

如果 I/O 未在 5 结束。,则 LOGGER 在 FIRST STAT 和 LAST STAT 之前执行。

另请参阅:https://jsblog.insiderattack.net/timers-immediates-and-process-nexttick-nodejs-event-loop-part-2-2c53fd511bb3#f3dd

关于javascript - 为什么 Node.js setImmediate 在 I/O 回调之后执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47970806/

相关文章:

asynchronous - 使用 redux-api-middleware 链接异步操作

javascript - 如何捕获堆栈溢出错误

javascript - 无法在 JavaScript 循环中从数据库获取数据

javascript - 从表格导入 Excel 中的数据

javascript - 使用 jQuery 将 SVG 元素插入到 HTML 标记中

javascript - 获取类的outerHeight并取最大值

javascript - JQuery:验证表单中的所有输入

javascript - 在 Javascript 中递归遍历树

node.js - 避免强制门户

node.js - gulp-exec 子进程立即关闭