1

Тема: SetTimeOut и SetInterval, что лучше использовать в JavaScript?

Для многократного запуска кода через равные промежутки времени предназначена функция setInterval. Тем не менее она обладает рядом минусов, в основном это разное поведение в различных браузерах.

Первое отличие состоит в разности момента установки таймера для следующего запуска. Создадим небольшой тест: будем отмерять количество времени, прошедшее с начала выполнения предыдущего запуска и с его окончания.

var d1 = new Date(), d2 = new Date();
setInterval(function() {
    var d = new Date();
    document.body.innerHTML += (d - d1) + ' ' + (d - d2) + '<br>';

    // Ставим метку в начале функции
    d1 = new Date();
    while (new Date() - d1 < 200);    // ничего не делаем 200 миллисекунд
    // И в конце функции
    d2 = new Date();
}, 1000);

Вывод будет информативным, начиная со второй строчки.

В Firefox, Opera, Safari и Chrome ситуация будет схожая: первое число будет примерно равно 1000, второе — на 200 меньше. Различие будут только в разбросе значений. Самый маленький разброс в Chrome и Opera.

Поделиться

2 (изменено: PunBB, 2017.06.08 15:45)

Re: SetTimeOut и SetInterval, что лучше использовать в JavaScript?

Ещё одно отличие менее заметное и более трудновоспроизводимое, но иногда способное доставить много хлопот, — это устойчивость к изменению системного времени. Если запустить следующий тест

setInterval(function() {
    document.body.innerHTML = Math.random();
}, 500);

И после запуска перевести системное время на минуту назад, то в браузерах Firefox и Safari смена чисел приостановится, а через минуту запустится вновь. Конечно, ручной перевод системного времени крайне редкая ситуация, но на многихсистемах настроена автоматическая синхронизация времени с серверами в интернете, поэтому в некоторых ситуациях нельзя сбрасывать со счетов этот фактор.

Ещё один маленький минус функции setInterval — чтобы была возможность остановить её действие, необходимо где-то запоминать её идентификатор, что не всегда удобно.

Поделиться

3

Re: Чем заменить setInterval

Чтобы избавиться от перечисленных недостатков setInterval можно использовать многократный setTimeout.

Важная альтернатива setInterval – рекурсивный setTimeout:

/** вместо:
var timerId = setInterval(function() {
  alert( "тик" );
}, 2000);
*/

var timerId = setTimeout(function tick() {
  alert( "тик" );
  timerId = setTimeout(tick, 2000);
}, 2000);

В коде выше следующее выполнение планируется сразу после окончания предыдущего.

Рекурсивный setTimeout – более гибкий метод тайминга, чем setInterval, так как время до следующего выполнения можно запланировать по-разному, в зависимости от результатов текущего.

Например, у нас есть сервис, который раз в 5 секунд опрашивает сервер на предмет новых данных. В случае, если сервер перегружен, можно увеличивать интервал опроса до 10, 20, 60 секунд… А потом вернуть обратно, когда всё нормализуется.

Если у нас регулярно проходят грузящие процессор задачи, то мы можем оценивать время, потраченное на их выполнение, и планировать следующий запуск раньше или позже.

Поделиться

4

Re: SetTimeOut и SetInterval, что лучше использовать в JavaScript?

Рекурсивный setTimeout гарантирует паузу между вызовами, setInterval – нет.

Давайте сравним два кода. Первый использует setInterval:

var i = 1;
setInterval(function() {
  func(i);
}, 100);

Второй использует рекурсивный setTimeout:

var i = 1;
setTimeout(function run() {
  func(i);
  setTimeout(run, 100);
}, 100);

При setInterval внутренний таймер будет срабатывать чётко каждые 100 мс и вызывать func(i):

Реальная пауза между вызовами func при setInterval меньше, чем указана в коде!

Это естественно, ведь время работы функции никак не учитывается, оно «съедает» часть интервала.

Возможно и такое что func оказалась сложнее, чем мы рассчитывали и выполнялась дольше, чем 100 мс.

В этом случае интерпретатор будет ждать, пока функция завершится, затем проверит таймер и, если время вызова setInterval уже подошло (или прошло), то следующий вызов произойдёт сразу же.

Если функция и выполняется дольше, чем пауза setInterval, то вызовы будут происходить вообще без перерыва.

Поделиться

5

Re: SetTimeOut и SetInterval, что лучше использовать в JavaScript?

Все зависит от поставленной задачи. Изначально SetTimeOut служит для однократного запуска таймера, а SetInterval для запуска цикла. Но и ту и другую функцию можно использовать для циклической прогонки скриптов, если например запустить рекурсивно в функции SetTimeOut, то она будет действовать практический аналогично SetInterval.

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

Но опять же повторюсь, если функция ил запрос минимизированы, то конечный пользователь вряд ли почувствует разницу.
Поэтому что использовать, решает каждый сам

Сайт sempai

Поделиться

6

Re: SetTimeOut и SetInterval, что лучше использовать в JavaScript?

Сборщик мусора в JavaScript не чистит функции, назначенные в таймерах, пока таймеры актуальны.

При передаче функции в setInterval/setTimeout создаётся внутренняя ссылка на неё, через которую браузер её будет запускать, и которая препятствует удалению из памяти, даже если функция анонимна.

// Функция будет жить в памяти, пока не сработал (или не был очищен) таймер
setTimeout(function() {}, 100);

Для setTimeout – внутренняя ссылка исчезнет после исполнения функции.
Для setInterval – ссылка исчезнет при очистке таймера.

Так как функция также тянет за собой всё замыкание, то ставшие неактуальными, но не отменённые setInterval могут приводить к излишним тратам памяти.

Добавлено: 2017.06.08 16:02

sempai, конечно каждый решает сам. Лично сам не пишу больших скриптов, поэтому пока использую таймаут.

Информация взята из вот ссылка

Поделиться

7 (изменено: sempai, 2017.06.08 16:27)

Re: SetTimeOut и SetInterval, что лучше использовать в JavaScript?

PunBB сказал:

Для setTimeout – внутренняя ссылка исчезнет после исполнения функции.Для setInterval – ссылка исчезнет при очистке таймера.

И все вместе исчезает к чертям после перехода (перезагрузки) страницы.  PunBB_INFO_ICQ/yes

PunBB сказал:

Лично сам не пишу больших скриптов, поэтому пока использую таймаут

По этой же причине использую интервал.


Offtopic: Блин, уже не первый раз замечаю, что под IE, местные смайлы не работают  PunBB_INFO_ICQ/wall

Сайт sempai

Поделиться