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
这是事件循环的一个“特性”吗?我一直认为它至少要在delay
ms之后触发。
2条答案
按热度按时间mklgxw1f1#
从NodeJS文档:
回调可能不会在精确的延迟毫秒内被调用。Node.js不保证回调触发的确切时间,也不保证它们的顺序。回调将尽可能接近指定的时间被调用。
随着间隔数量的增加(你有100个),准确度会下降,例如,有1000个间隔时准确度会更差。有10个间隔时准确度会更好。随着NodeJS必须跟踪更多间隔,准确度会下降。
我们可以假设算法有一个“合理的增量”来决定最终的准确性,它不包括检查以确保它在指定的间隔之后,也就是说,在源代码中进行一些挖掘很容易找到。
另见How is setTimeout implemented in node.js,其中包括更多细节,初步的来源调查似乎证实了这一点,以及上述内容。
wn9m85ua2#
从节点定时器文档,关于设置超时:
唯一的保证是超时不会早于声明的超时间隔执行