Почему вызовы setInterval не регулируются для первых 4 выполнений? - PullRequest
2 голосов
/ 11 марта 2019

Известно, что тайм-ауты в JavaScript сокращаются каждые 4 мс на активной вкладке и каждые 1000 мс на неактивной . Это поведение может немного измениться в зависимости от браузера и конфигурации, но обычно оно одинаковое.

Для полноты приведу здесь соответствующую часть:

Время ожидания уменьшено до> = 4 мс

В современных браузерах вызовы setTimeout() / setInterval() сокращаются до минимума один раз каждые 4 мс, когда срабатывают последовательные вызовы из-за вложенности обратного вызова (где уровень вложенности составляет по крайней мере определенную глубину) или после определенного числа последовательных интервалов.

Я хотел доказать это кому-нибудь, используя этот фрагмент в экземпляре Chrome по умолчанию:

let beforeStartingTheInterval = Date.now();
let intervalId = setInterval(()=>{ 
  let msPassed = Date.now()-beforeStartingTheInterval;
  if (msPassed > 20) clearInterval(intervalId); // stop after 20 ms
  console.log( msPassed + "ms have passed after starting the interval")
  }
,0);

И почти каждый раз, когда я запускал этот код, я получал такой вывод:

1ms have passed after starting the interval
2ms have passed after starting the interval
3ms have passed after starting the interval
4ms have passed after starting the interval
8ms have passed after starting the interval
12ms have passed after starting the interval
16ms have passed after starting the interval
20ms have passed after starting the interval

Как видно, интервал (обычно) запускается один раз в миллисекунду первые четыре раза, а затем каждые> = 4 мс.

Почему для первых 4 исполнений вызовы не регулируются? Я ожидал этот вывод:

4ms have passed after starting the interval
8ms have passed after starting the interval
12ms have passed after starting the interval
16ms have passed after starting the interval
20ms have passed after starting the interval

Или хотя бы один, который имеет минимум 4 мс между любыми двумя исполнениями (даже первыми)

Ответы [ 4 ]

1 голос
/ 11 марта 2019

Почему для первых 4 исполнений вызовы не регулируются?

Полагаю, первый вопрос, который следует задать, это Почему таймер вообще задушен?

Ну, некоторые из них могут быть такими, что такие короткие таймеры запуска

1) сложно реализовать, так как вам нужно либо использовать аппаратный таймер, либо проверить время внутри цикла, чтобы иметь возможность точно планировать время, цикл должен работать очень быстро.

2) потребляет много батареи / вычислительного времени

3), вероятно, вообще не нужны, так как дисплей обновляется примерно каждые 60 кадров в секунду, то есть каждые 16 мс, поэтому, если вы используете таймер, который работает так быстро, вы на самом деле не увидите вывод с этой скоростью.

Тогда следующий вопрос может быть Почему тогда вообще используются такие короткие таймеры?

На самом деле есть несколько веских причин:

1) Отложить действие после а) текущий кодовый блок, возьмите, например, React's setState б) DOM rerender

2) Выполнять длительные задачи «асинхронно» в главном потоке, не блокируя пользовательский интерфейс, через некоторое время освобождая его на миллисекунду.

Поэтому в браузере возникает проблема при настройке времени таймера:

Если он ограничивает время, например, setState на 4 мс, страница может загружаться медленнее в целом. Однако, если он не ограничивает setInterval, который запускается излишне быстро, он расходует батарею пользователя (большинство пользователей в настоящее время пользуются мобильным телефоном).

Поэтому имеет смысл, что браузер очень быстро выполняет несколько таймеров, так что setTimeout(deferred, 0) запускается сразу, а затем несколько раз дросселирует, чтобы уменьшить негативное влияние неправильно выполненных таймеров рендеринга / алгоритмов длительного запуска.

«4ms» после «5 раз», вероятно, являются сбалансированным результатом этого рассмотрения.

0 голосов
/ 11 марта 2019

https://humanwhocodes.com/blog/2011/12/14/timer-resolution-in-browsers/

Большинство браузеров также выполняют некоторое регулирование таймера в зависимости от различных условий. Цель состоит в том, чтобы сэкономить заряд батареи в подходящее время - когда теоретически вы либо не заметите разницы, либо с удовольствием обменяетесь на увеличение времени автономной работы на ноутбуке или мобильном устройстве. Вот некоторые обстоятельства, при которых изменяется разрешение таймера:

0 голосов
/ 11 марта 2019

Проведя некоторое время в Интернете, я обнаружил, что это стандарт HTML5 :

Примечание. Таймеры могут быть вложенными;однако после пяти таких вложенных таймеров интервал должен составлять не менее четырех миллисекунд.

0 голосов
/ 11 марта 2019

Ответ содержится в документации, которую вы связали с (выделено мной)

В Chrome и Firefox 5-й последовательный обратный вызов фиксируется ; Зажимы Safari на 6-й звонок; в крае его третий. Gecko начал обрабатывать setInterval () таким образом в версии 56 (он уже делал это с setTimeout (); см. Ниже).

...