setInterval与chrome和firefox不同

时间:2019-05-24 03:20:01

标签: javascript settimeout setinterval

以下代码在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)

3 个答案:

答案 0 :(得分:2)

setTimeout将您的请求排入指定延迟后的第一个机会。一旦延迟过去并且调用堆栈为空,您的请求就会得到处理。这意味着时间会略有变化,具体取决于浏览器引擎的运行情况。

答案 1 :(得分:1)

这是因为Chrome's implementation of 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实际上取决于首先安排的timeoutinterval中的哪个间隔。

还要注意,Chrome的行为可能会在不久的将来成为标准行为:https://github.com/whatwg/html/issues/3151

答案 2 :(得分:0)

由于两个浏览器之间的代码差异而导致差异。

  1. 如果您颠倒间隔和超时计时器的启动顺序,则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)

  1. 如果您保持与帖子中相同的顺序,但将阻止时间减少到50毫秒,则间隔时间将在Chrome中的400毫秒标记处调用,并在阻止事件循环时阻止调用超时。但是在Firefox中,将首先调用400ms的setTimeout,清除间隔计时器,并完全阻止间隔计时器在400ms标记处被调用。

简而言之,两个浏览器对间隔和计时器的超时处理的编码方式不同,在上述情况2中,Firefox似乎在间隔计时器调用之间增加了10ms的间隔(Section 7.5 of HTML 5.2中允许)。