setInterval отличается от Chrome и Firefox - PullRequest
0 голосов
/ 24 мая 2019

следующий код печатает разные результаты для 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

firefox 67 print:

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 ]

2 голосов
/ 24 мая 2019

setTimeout ставит ваш запрос в очередь при первой возможности после указанной задержки.Как только задержка истечет , а стек вызовов пуст , ваш запрос будет обработан.Это означает, что могут быть небольшие изменения во времени в зависимости от того, что еще работает движок браузера.

1 голос
/ 24 мая 2019

Это потому, что реализация 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

0 голосов
/ 24 мая 2019

Разница возникает из-за различий в коде между двумя браузерами.

  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)
Если вы сохраняете тот же порядок, что и в посте, но уменьшаете блокировку, скажем, до 50 миллисекунд, интервал вызывается с отметкой 400 мс в Chrome и блокирует время ожидания, пока он блокирует цикл обработки событий.Но в Firefox setTimeout для 400 мс вызывается первым, очищает таймер интервала и вообще не вызывает таймер интервала при отметке 400 мс.

Короче говоря, обработка тайм-аутов для интервалов и таймеров кодируется по-разномув двух браузерах и в случае 2 выше Firefox добавляет 10 мс к интервалу между вызовами с интервальным таймером (как это разрешено в разделе 7.5 HTML 5.2 ).

...