Javascript setTimeout()的触发时间比预期的稍早

Javascript setTimeout()的触发时间比预期的稍早,javascript,node.js,settimeout,event-loop,Javascript,Node.js,Settimeout,Event Loop,UPD:问题是为什么JavaScript中的计时器通常不准确,所有提到的不准确之处都是关于在指定延迟之后的调用。这里我要问的是,为什么NodeJS甚至在延迟之前也能容忍调用?这不是一个容易出错的计时器设计吗 刚刚发现NodeJSsetTimeout()的一个意外行为(仅限我?)。有时它会在指定延迟之前触发 function main() { let count = 100; while (count--) { const start = process.hrtime();

UPD:问题是为什么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.js不保证调用的确切时间,也不保证调用的顺序。将在尽可能接近指定时间的情况下调用回调

随着间隔数的增加(有100个间隔),精确度会降低,例如,如果间隔数为1000,精确度会更差。十点比较好。由于NodeJS必须跟踪更多的间隔,因此其精度将降低

我们可以假定算法有一个“合理的增量”来决定最终的精度,它不包括检查以确保它在指定的间隔之后。也就是说,通过对源头的挖掘,很容易找到答案


另请参阅,其中包括更多详细信息,初步的来源调查似乎证实了这一点和上述情况。

我已经重复了这个问题。我试图将
setTimeout(…)
放在一个类似
(函数(start,delay){…})(start,delay)的函数中并且它似乎减少了在预期之前触发的事件数。但我仍然没有解释。延迟短了几分之一毫秒。我想这差不多是你能得到的了。重复?可能重复为什么投票被否决?这个问题完全正确。我刚刚遇到了一个中断的测试用例,因为它预期超时时间至少为指定的毫秒数。一开始我没有意识到这个错误。我不希望它在
delay
ms之后被调用。我只希望它在
delay
之后被调用。但在我的示例中,它是在指定的时间之前调用的。表达式“尽可能接近指定的时间”并不意味着在指定的时间之后。可能是以前。提供了更多的信息。@IvanVelichko“尽可能接近”对之前/之后没有任何影响。在这种环境下,海事组织的不准确是可以预料的。也要考虑你的时间间隔。间隔数越少,误差就越小,间隔数越多,误差就越大。由于它必须检查更多的间隔,其精度将降低,并且无论它使用什么算法来查看间隔是否“足够接近”,都将确定最终的精度。
$ 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