javascript - Nodejs 事件循环——与顶层代码的交互

标签 javascript node.js timer event-loop

希望对 node.js 执行模型的理解有一点确认。我知道当 node.js 进程启动时,这是执行顺序: enter image description here (来自 Jonas Schmedtmann 的 Udemy node.js 类(class))

主要要点是顶层代码总是在任何回调之前首先执行。

然后,在事件循环中,这是“阶段”的顺序: enter image description here

经过一些挖掘,我还确认了为什么在主模块中调用的 setTimeout 和 setImmediate 具有“任意”执行顺序,但是当从 I/O 阶段调用时,setImmediate 将始终首先执行,基于这篇文章: https://github.com/nodejs/help/issues/392#issuecomment-274032320 .

(原因:假设计时器阈值已经过去,因为我们当前处于 I/O 阶段,之后的下一个阶段是执行 setImmediate 回调的检查处理阶段,immediate 总是在计时器之前执行。)

现在,当从一个阶段调用计时器和立即回调时,下一阶段是到期计时器阶段(例如从主模块),如果顶级代码花费的时间足够长以至于计时器到期,则计时器回调总是先执行,对吗?我用下面的代码对此进行了测试,它似乎是真的(每次我运行它时,计时器都会先执行,尽管与立即回调相比它有整整一秒的延迟)

setTimeout(() => {
  console.log('timer completed');
}, 1000);

setImmediate(() => {
  console.log('immediate completed');
});

for (let i = 0; i < 5000; i++) {
  console.log(`top-level code: ${i}`);
}

所以这是我的问题:由于事件循环,I/O 操作回调是否也应该在立即回调之前执行,假设顶层代码花费足够长的时间 I/O 操作完成我们开始事件循环的时间?

但是,下面的代码表明情况并非如此,因为执行顺序始终是:top-levels->timer->immediate->io

即使基于上面的模型,我也应该期待:top-levels->timer->io->immediate (?)

setTimeout(() => {
  console.log('timer completed');
}, 1000);

fs.readFile('test-file.txt', 'utf-8', () => {
  console.log('io completed');
});

setImmediate(() => {
  console.log('immediate completed');
});

for (let i = 0; i < 5000; i++) {
  console.log(`top-level code: ${i}`);
}

谢谢!

最佳答案

我回答这个问题可能有点晚了,您可能已经想通了@M.Lee。但是这里是你问题的答案:

在顶层代码执行期间,您在示例中运行的代码并未在事件循环中运行。就像您问题中的第一张图片所示,事件循环将在顶层代码执行后开始计时。因此,当谈到顶层代码时,Node 不会遵循它在事件循环 tick 期间遵循的相同顺序。

在这种特殊情况下,I/O 回调最后执行显然是因为这个特殊文件的内容(顺便说一句,我不得不继续研究 Jonas 的 Node 类(class)和了解此文件包含的内容。它只包含一行“Node.js 是最好的!”一百万次)。

这里还有一个旁注是您正在使用异步 readFile 函数而不是 readFileSync

关于javascript - Nodejs 事件循环——与顶层代码的交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60198686/

相关文章:

javascript - 倒计时达到 0 时发出蜂鸣声

javascript - 嵌套 AngularJS 模态

javascript - 停止 javascript 执行直到 jquery JSON 响应

json - 使用 ReactJS 和 AJAX 更新页面内容

javascript - 同步使用 ImageMagic

linux - Linux内核add_timer的可靠性只有一个小问题吗?

c# - 我可以在没有定时器组件的情况下使用定时器吗?

javascript - 当复选框长度大于 1 时,提交按钮不启用

javascript - 使用 video.js 在 ios 上内联播放视频?

javascript - Puppeteer:从网站获取 localStorage