我正在此测试脚本的节点8.11
上运行:
let end = false;
let i = 0;
setInterval(() => { i++; }).unref();
let k = 0;
async function loop() {
k++
if (end === false)
setImmediate(loop);
}
console.time('test');
loop()
.then(() => {
setTimeout(() => {
end = true;
console.log('interval', i);
console.log('recursion', k);
console.timeEnd('test');
}, 1000);
})
输出为:
interval 997
recursion 824687
test: 1001.831ms
但是,如果我评论这两行:
// if (end === false)
// setImmediate(loop);
结果是:
interval 537
recursion 1
test: 1003.882ms
我对phases of nodejs进行了艰苦的研究,但我不明白为什么setImmediate
应该影响间隔函数的结果。
您有一些解释吗?
谢谢
答案 0 :(得分:1)
那是因为在节点js上的计时器就不是精确的,因为它们只是事件循环中的事件,因此他们无法确切知道何时触发它们,这就是为什么setTimeout表示它将至少在您提供的时间。
不能依赖设置的超时间隔来执行 在精确的毫秒数之后。这是因为其他 执行阻止或保留在事件循环中的代码将推动 执行超时返回。唯一的保证是超时 不会早于声明的超时间隔执行。
设置setInmediate时,您在事件循环中填充了许多中间事件,因此将超时事件推回队列。
请记住,事件循环周期的时间长短不一(确切),因此,即使您认为setInmediate不应影响计时器,您也要延长事件循环的时间长。
有趣的文章
https://nodejs.org/en/docs/guides/timers-in-node/
编辑:正如您所指出的,在您的情况下相反,使用setInmediate时会有更多的迭代。在那种情况下,这可能与事件循环的速度取决于程序的负载是动态的有关。