【发布时间】:2021-09-04 04:37:08
【问题描述】:
如果您创建一个非常简单的程序,它有一个延迟 1 秒的 setInterval,并记录调用其函数的时间,您会注意到间隔“漂移”。
基本上,每次调用之间实际上需要(1,000 毫秒 + 一些时间)。
对于这个程序,每次调用之间实际上需要大约 1,005 毫秒。
漂移的原因是什么?
重新排队 setInterval 需要 5 毫秒吗?
是运行函数所需的时间长度吗? (我对此表示怀疑,但无法得出结论。)
为什么 setInterval 会以这种方式运行,而不仅仅是基于某个时钟时间? (例如,如果您有 1,000 毫秒的延迟并且您在时间 3 开始...只需检查 1,003 和 2,003 等是否已经过去?)
示例:
const startTime = new Date().valueOf();
function printElapsedTime(startTime) {
console.log(new Date().valueOf() - startTime);
}
let intervalObj = setInterval(printElapsedTime, 1000, startTime);
输出: 1005 2010 3015 4020
所以你不再同步到 1 秒。由于它漂移了大约 5,因此在运行 100 次后,它将比预期“晚”运行半秒。
This question 讨论了如何避免这种漂移,但没有解释为什么会发生这种漂移。 (因为它并没有说 setInterval 在每次调用后递归地将自身添加到事件队列中 - 这需要 3ms ......这只是对漂移原因的猜测)。
【问题讨论】:
-
链接的答案没有解释为什么存在漂移。如果您想避免漂移,它只是提供修复。
-
规范只说了以下内容:“此 API 不保证计时器将按计划准确触发。由于 CPU 负载、其他任务等原因导致的延迟是可以预料的。” html.spec.whatwg.org/multipage/…
-
或许熟悉 Chrome 或 Node 实现的人可以解答
-
还有更多:步骤 17 允许算法在排队回调之前等待任意时间(如果我理解正确的话)“这是为了让用户代理将超时填充为需要优化设备的电源使用。例如,某些处理器具有低功耗模式,其中计时器的粒度会降低;在此类平台上,用户代理可以减慢计时器以适应此时间表,而不是要求处理器使用更准确的模式及其相关的更高功耗。” 如果内存正常,这会发生在没有聚焦的浏览器选项卡中。
-
没有什么可回答的:超时只能保证至少您指定的时间量。如果它们需要更长的时间,那是符合规范的。然后,您还需要与所有现代浏览器都应用间隔限制的事实相结合,因此您会得到前几个“按要求”,之后最小间隔在前台变为 4ms,在后台变为惊人的“许多秒”。