Reputation: 41
The following code prints different result between Firefox and 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 print:
100
351
605
timeout 855
firefox 67 print:
101
351
timeout 601
why?
add setTimeout delay, the result is still different.
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)
Upvotes: 0
Views: 1990
Reputation: 136627
That's because Chrome's implementation of setInterval
does correct the drift between each call.
So instead of blindly calling again setTimeout(fn, 250)
at the end of the interval's callback, it actually does setTimeout(fn, max(now - 250, 0))
.
So this gives
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
Note that the last interval @600
is actually dependent on which of timeout
or interval
as been scheduled first.
And also note that Chrome's behavior may become the standard in a near future: https://github.com/whatwg/html/issues/3151
Upvotes: 3
Reputation: 19301
The difference arises because of code differences between the two browsers.
"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)
In short, timeout processing for intervals and timers is coded differently in the two browsers, and in case 2 above, Firefox appears to add 10ms to the interval between interval-timer calls (as allowed in Section 7.5 of HTML 5.2).
Upvotes: 0
Reputation: 27245
setTimeout queues your request to be handled at the first opportunity after the specified delay. Once the delay has elapsed and the call stack is empty your request is handled. This means there can be slight variations in the timing depending on what else the browser’s engine has going on.
Upvotes: 2