setTimeout()比预期的更早触发

时间:2018-04-17 13:01:37

标签: javascript node.js settimeout event-loop

UPD :问题What is the reason JavaScript setTimeout is so inaccurate?询问为什么JavaScript中的计时器一般都不准确,并且所有提到的不准确性都是在指定的延迟后略微调用。在这里,我问为什么NodeJS甚至在延迟之前也能容忍调用?这不是一个容易出错的计时器设计吗?

刚刚发现了NodeJS setTimeout()的意外(仅限我?)行为。有时它会比指定的延迟更早触发。

function main() {
  let count = 100;
  while (count--) {
    const start = process.hrtime();
    const delay = Math.floor(Math.random() * 1000);

    setTimeout(() => {
      const end = process.hrtime(start);
      const elapsed = (end[0] * 1000 + end[1]/1e6);
      const dt = elapsed - delay;
      if (dt < 0) {
        console.log('triggered before delay', delay, dt);
      }
    }, delay);
  }
}

main();

我的笔记本电脑输出是:

$ node --version
$ v8.7.0

$ node test.js
triggered before delay 73 -0.156439000000006
triggered before delay 364 -0.028260999999986325
triggered before delay 408 -0.1185689999999795
triggered before delay 598 -0.19596799999999348
triggered before delay 750 -0.351709000000028

这是一个&#34;功能&#34;事件循环?我一直认为必须至少在delay ms之后触发它。

1 个答案:

答案 0 :(得分:3)

来自NodeJS docs

  

可能不会在精确延迟的毫秒内调用回调。 Node.js不保证回调何时触发的确切时间,也不保证它们的排序。回调将尽可能接近指定的时间调用。

当您增加间隔数(您有100个)时,准确度会降低,例如,1000个间隔的准确度会更差。十点好多了。由于NodeJS必须跟踪更多的时间间隔,因此其精度会降低。

我们可以认为算法有一个合理的delta&#34;这决定了最终的准确性,它不包括检查以确定它在指定的时间间隔之后。也就是说,很容易找到一些挖掘源。

另请参阅How is setTimeout implemented in node.js,其中包含更多详细信息,初步来源调查似乎也证实了这一点以及上述内容。