以下代码在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)
Chrome 74印刷:
100
351
605
timeout 855
Firefox 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)
settimeout在指定的延迟后以第一个机会处理您的请求。一旦延迟经过,并且呼叫堆栈为空您的请求将被处理。这意味着根据浏览器的发动机还在进行的情况下,定时可能会有些变化。
这是因为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
由于两个浏览器之间的代码差异而产生的差异。
- 如果您扭转了启动间隔和超时计时器的顺序,则Chrome的行为与Firefox相同:
"use strict";
var start = Date.now()
setTimeout(function timeout() { // start the timeout first
clearInterval(id)
console.log('timeout',Date.now() - start)
}, 400)
var id = setInterval(function interval() {
var whileStart = Date.now()
console.log(whileStart - start)
while (Date.now() - whileStart < 250) {
}
}, 100)
- 如果您保留与帖子中相同的订单,但将阻塞减少到50毫秒,则间隔时间在Chrome中的400ms标记处被调用,并在阻止事件循环时阻止了暂停。但是在Firefox中,首先调用400ms的Settimeout,清除了间隔计时器,并防止以400ms标记为400ms的间隔计时器。
简而言之,间隔和计时器的超时处理在两个浏览器中的编码不同,在上面的情况下,Firefox似乎在间隔调用调用之间的间隔中增加了10ms(如HTML 5.2的7.5节所示(。