qinshenxue.com
qinshenxue.com

Reputation: 41

setInterval different from chrome and firefox

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

Answers (3)

Kaiido
Kaiido

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

traktor
traktor

Reputation: 19301

The difference arises because of code differences between the two browsers.

  1. If you reverse the order of starting the interval and timeout timers, Chrome behaves the same as 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)

  1. If you keep the same order as in the post but reduce the blocking to, say, 50 milliseconds, the interval time gets called at the 400ms mark in Chrome and blocks the timeout being called while it blocks the event loop. But in Firefox the setTimeout for 400ms gets called first, clears the interval timer and prevents the interval timer being called at all at the 400ms mark.

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

ray
ray

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

Related Questions