javascript - setInterval 不同于 chrome 和 firefox
问题描述
以下代码在 Firefox 和 Chrome 之间打印不同的结果
var start = Date.now()
var id = setInterval(function interval() {
var whileStart = Date.now()
console.log(whileStart - start)
while (Date.now() - whileStart < 250) {
}
}, 100)
setTimeout(function timeout() {
clearInterval(id)
console.log('timeout',Date.now() - start)
}, 400)
镀铬 74 打印:
100
351
605
timeout 855
火狐 67 打印:
101
351
timeout 601
为什么?
加上 setTimeout 延迟,结果还是不一样。
var start = Date.now()
var id = setInterval(function interval() {
var whileStart = Date.now()
console.log(whileStart - start)
while (Date.now() - whileStart < 250) {
}
}, 100)
setTimeout(function timeout() {
clearInterval(id)
console.log('timeout',Date.now() - start)
}, 500)
解决方案
这是因为Chrome 的实现setInterval
确实纠正了每次调用之间的偏差。因此,与其在间隔回调结束时盲目地再次setTimeout(fn, 250)
调用,它实际上是setTimeout(fn, max(now - 250, 0))
.
所以这给了
t Firefox (no drift control) | Chrome (drift control)
––––––––––––––––––––––––––––––––––––––––––––––––––––––––
0 schedule interval @100ms schedule interval @100ms
0 schedule timeout @400ms schedule timeout @400ms
100 exec interval callback exec interval callback
=> block 250ms => block 250ms
... ...
350 schedule interval @450ms schedule interval @350ms
(now + 100ms) (now + max(100ms - 250ms, 0))
350 exec interval callback
=> block 250ms
400 exec timeout callback ...
=> cancel interval ...
...
600 schedule interval @600ms
exec interval callback
=> block 250ms
...
850 schedule interval @850ms
exec timeout callback
=> cancel interval
请注意,最后一个间隔@600
实际上取决于哪个timeout
或interval
首先安排的时间。
还要注意 Chrome 的行为可能在不久的将来成为标准:https ://github.com/whatwg/html/issues/3151
推荐阅读
- c++ - 涉及两位数时正确显示网格图?
- python - PyQt5 - 动态添加小部件到布局
- c++ - 交换指针:相当于`std::unique_ptr::swap`
- python - Plotly:旭日形图未正确渲染
- java - 使用两个线程打印偶数和奇数
- unix - sed: -e expression #1, char 20: Jenkins Pipeline 中未终止的“s”命令
- c++ - openGL何时以及如何计算F_depth(深度值)
- javascript - 未捕获的类型错误:使用 -http://localhost:8080/ 时无法读取 null- 的属性“长度”
- php - Codeigniter 4 自动路由模块
- java - 为什么 ClassCastException 只发生在运行时?