【问题标题】:NodeJS setImmediate loop: Is only one setImmediate callback executed per iteration of the event loop?NodeJS setImmediate 循环:事件循环的每次迭代是否只执行一个 setImmediate 回调?
【发布时间】:2023-02-03 15:49:15
【问题描述】:
function loop() {
  // Anything you want to run in a loop can be here

  setImmediate(loop);
}

loop();

在这种情况下,setImmediate回调正在调用另一个setImmediate,其回调最终进入队列(“检查”阶段)。因此loop()重复运行

事件循环的每次迭代是否只运行一个 setImmediate 回调?即 loop() 每次事件循环迭代只运行一次吗?

我经常听说 setImmediate 用于在事件循环的下一个“滴答”或迭代运行回调

但是,关于事件循环的官方 Node 文档 (https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/) 说:

“通常,当事件循环进入给定阶段时,它将执行特定于该阶段的任何操作,然后在该阶段的队列中执行回调,直到队列耗尽或执行了最大数量的回调。”

这让我认为在事件循环的每次迭代中可能会运行多个 setImmediate 回调。如果是这种情况,我们怎么知道每个“tick”执行了多少setImmediate回调?

谢谢你的帮助!

【问题讨论】:

  • 这里有 2 种情况:在同一执行中安排多个回调 (setImmediate(cb1); setImmediate(cb2)) 和您公开 setImmediate(() =&gt; { cb1(); setImmediate(cb2); }) 的递归情况。第一种情况显然会在同一帧中安排 cb1cb2(在节点 <=10 中,它甚至不会让 Promise 回调在其间执行)。第二种情况将在其自己的框架中执行每个回调,让其他阶段在其间做自己的事情。

标签: javascript node.js event-loop setimmediate


【解决方案1】:

考虑循环在特定条件下终止。 setImmediate()回调将在每次loop的执行结束时调用。作为doc

setImmediate() 旨在在当前轮询完成后执行脚本 阶段完成。

简单来说,它是您传递的函数的回调,它将在每次执行时执行。

考虑以下示例,您将在输出中观察到 currentCount 值在函数结束时递增,或者如文档所述,在每次“滴答”时递增。

const count = 5;
let currentCount = 0;
const array = [];

function loop() {
  console.log('start', currentCount);
  let a = setImmediate((...args) => {
    if (currentCount == count) {
      array.forEach((b) => clearImmediate(b));
    } else {
      console.log(...args, currentCount);
      setTimeout(loop, 1000);
    }
  }, 'data');
  currentCount++;
  array.push(a);
  console.log('end', currentCount);
}

loop();

输出:

❯ node index.js
start 0
end 1
data 1
start 1
end 2
data 2
start 2
end 3
data 3
start 3
end 4
data 4
start 4
end 5

【讨论】:

  • 谢谢你,雪莉。我想赞扬你花时间提供帮助,尽管我的声誉还不够高,无法这样做。但是,我也很难理解你的代码示例,我认为包含 setTimeout() 似乎会使事情复杂化,因为我们现在需要考虑事件循环的另一个阶段(即“计时器”阶段)
最近更新 更多