JavaScript метод WindowOrWorkerGlobalScope.setInterval()

JavaScript WindowOrWorkerGlobalScope

Определение и применение

JavaScript метод setInterval() объекта WindowOrWorkerGlobalScope многократно вызывает функцию или выполняет фрагмент кода с фиксированной задержкой времени между каждым вызовом.


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


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

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

Пул идентификаторов, используемых методами setTimeout() и setInterval() являются общими, что означает, что вы можете технически использовать методы clearTimeout() и clearInterval() взаимозаменяемо. Однако для ясности вам следует избегать этого.

Поддержка браузерами

МетодChrome
Chrome
Firefox
Firefox
Opera
Opera
Safari
Safari
Internet Explorer
IExplorer
Microsoft Edge
Edge
setInterval()ДаДаДаДаДаДа

JavaScript синтаксис:

const timeoutID = scope.setInterval(function, delay);
const timeoutID = scope.setInterval(function, delay, param1, ..., paramX);
const timeoutID = scope.setInterval(code, delay); // не рекомендуемый синтаксис

function - Function
delay - Integer
param1, ..., paramX - Any
code - String

Cпецификация

Document Object Model (DOM) Level 0

Значения параметров

ПараметрОписание
functionФункция, которая будет многократно выполняться после истечения таймера.
delayВремя в миллисекундах, которое таймер должен ждать перед выполнением указанной функции или кода. Если этот параметр опущен, то используется значение 0, оно означает, что выполнение должно произойти немедленно, или, точнее, как можно скорее (как только завершат работу все обработчики событий). Если этот параметр меньше 4, то используется значение 4. Обратите внимание, что в любом случае фактическая задержка может быть больше, чем предполагалось, причины задержек перечислены ниже в примерах.
param1, ..., paramXДополнительные параметры, передаваемые функции, указанной функцией или кодом, по истечении таймера. Передача дополнительных параметров функции в первом синтаксисе не работает в Internet Explorer 9 и ниже. Если вы хотите включить эту функцию в этом браузере, необходимо использовать полифилл.
codeАльтернативный синтаксис, который позволяет включать строку вместо функции, которая компилируется и выполняется по истечении таймера. Этот синтаксис не рекомендован к использованию в связи с угрозой безопасности.

Пример использования

Базовое использование

<!DOCTYPE html>
<html>
	<head>
		<title>Использование JavaScript методов setInterval() и clearInterval() объекта WindowOrWorkerGlobalScope</title>
	</head>
	<body>
		<button onclick = "runCounter()">Run counter</button> <!-- добавляем атрибут событий onclick -->
		<button onclick = "clearMyTimeOut()">Clear timeout and reset counter</button> <!-- добавляем атрибут событий onclick -->
		<span id = "counter">0</span>
		<script>
	let timeoutID; // создаем пустую переменную
	let counter = 0; // инициализируем переменную числовым значением

	function showCounter() {
	  counter++; // инкрементируем значение переменной
	  document.getElementById("counter").innerHTML = counter; // находим элемент по id и изменяем его содержимое значением переменной
	}
	function clearMyTimeOut() {
	  clearInterval(timeoutID); // отменяем повторяющееся выполнение программного кода, которое было ранее установлено вызовом метода setInterval()
	  counter = 0; // присваиваем значение переменной
	  document.getElementById("counter").innerHTML = counter; // находим элемент по id и изменяем его содержимое значением переменной
	}
	function runCounter() {
	  timeoutID = setInterval(showCounter, 1000); // задаем таймер, который многократно выполняет функцию каждые 1000 миллисекунд (1 секунда)
	}
		</script>
	</body>
</html>

В этом примере с использованием атрибута событий onclick при нажатии на первую кнопку (HTML элемент <button>) вызываем функцию runCounter(), которая с использованием JavaScript метода setInterval() задает таймер, который многократно выполняет функцию showCounter() каждые 1000 миллисекунд (1 секундa).

Функция showCounter() в свою очередь инкрементирует (увеличивает на 1) значение переменной counter, с помощью метода getElementById() находит элемент с определенным глобальным атрибутом id и изменяет его содержимое значением переменной counter.

С использованием атрибута событий onclick при нажатии на вторую кнопку (HTML элемент <button>) вызываем функцию clearMyTimeOut(), которая с использованием JavaScript метода clearInterval() отменяет повторяющееся выполнение программного кода, которое было ранее установлено вызовом метода setInterval(), устанавливает значение переменной counter равное нулю и добавляет элементу <span> это содержимое.

Результат нашего примера:

Пример использования методов setInterval() и clearInterval() объекта WindowOrWorkerGlobalScope
Пример использования методов setInterval() и clearInterval() объекта WindowOrWorkerGlobalScope

Проблема с this

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

Код, выполняемый setInterval(), вызывается из контекста выполнения, отдельного от функции, из которой был вызван setInterval(). Обычные правила установки контекста для ключевого слова this для вызываемой функции применяются, и если вы не установили его явно в вызове или с определенной привязкой, то он по умолчанию будет глобальным (или оконным) объектом в нестрогом режиме или будет неопределенным в строгом режиме. Он не будет таким же, как this для функции, которая вызвала метод setInterval(). Значение this по умолчанию метода setInterval() по-прежнему будет объектом window, а не неопределенным, даже в строгом режиме. Давайте рассмотрим следующий пример:

const myObj = {
  arr: ["a", "b", "c"],
  method: function(x) { console.log("Элемент " + this.arr[x]);} // выводим в консоль определенный элемент массива
}

myObj.method(1);
Элемент b

myObj.method(2);
Элемент c

setInterval(myObj.method, 1000, 1); // Cannot read property '1' of undefined (повторяющаяся ошибка)

Обратите внимание, что при передаче метода методу setInterval() мы получаем ошибку. Оптимальным и самым простым решением этой проблемы в данном случае будет использование анонимной функции обертки:

setInterval(function(){ myObj.method(2) }, 1000); // с передачей дополнительных параметров вызываемому методу внутри анонимной функции
Элемент c (повторяющийся вывод)
setInterval(function(x){ myObj.method(x) }, 1000, 2); // с передачей дополнительных параметров анонимной функции и вызываемому методу
Элемент c (повторяющийся вывод)

// с использованием стрелочных функций
setInterval(() => { myObj.method(1) }, 1000); // с передачей дополнительных параметров вызываемому методу внутри анонимной функции
Элемент b (повторяющийся вывод)
setInterval((x) => { myObj.method(x) }, 1000, 1);  // с передачей дополнительных параметров анонимной функции и вызываемому методу
Элемент b (повторяющийся вывод)

Передача строковых литералов

Метод setInterval() имеет альтернативный синтаксис, который позволяет включать строку вместо функции, которая компилируется и выполняется по истечении таймера:

// не рекомендованный синтаксис
setInterval("console.log('hello');", 1000);

// рекомендованный синтаксис
setInterval(myFunc, 1000);
setInterval(function() { console.log("hello"); }, 1000);
setInterval(() => { console.log("hello"); }, 1000); // допускается использование стрелочных функций

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

Максимальная задержка выполнения

Браузеры, включая Internet Explorer, Chrome, Safari и Firefox хранят значение тайм-аута как 32-разрядное целое число со знаком внутри. Значения выше 2147483647 миллисекунд (около 24,8 дней) вызовут переполнение, в результате чего вызов переданной функции произойдет немедленно.

Причины увеличения задержек

Давайте с Вами рассмотрим распространенные причины по которым тайм-аут может занять больше времени, чем ожидалось.

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

Чтобы уменьшить нагрузку (и связанное с ней использование батареи) с фоновых вкладок, тайм-ауты регулируются до срабатывания не чаще одного раза в секунду (1000 миллисекунд) в неактивных вкладках.

На увеличение задержки также может повлить, когда страница (или сама ОС/браузер) занята другими задачами. Важно отметить, что функция или фрагмент кода не могут быть выполнены до тех пор, пока поток, вызвавший setInterval() не завершится, например:

function f() {
  console.log("f has been called");
}
setInterval(f, 0);
console.log("after setInterval");

// вывод в консоль будет следующий:
after setInterval
f has been called

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

Длительность выполнения меньше интервала

Если существует вероятность того, что выполнение логики может занять больше времени, чем интервал времени, то рекомендуется вместо использования метода setInterval() рекурсивно вызвать именованную функцию с помощью метода setTimeout(). Например, при использовании setInterval() для опроса удаленного сервера каждые 5 секунд задержка в сети, не отвечающий сервер и множество других проблем могут помешать выполнению запроса в отведенное время. Таким образом, вы можете оказаться в очереди с запросами XHR, которые не обязательно вернутся в необходимом порядке. В этих случаях предпочтителен рекурсивный вызов метода setTimeout():

(function loop(){
   setTimeout(function() {
      // ваш код

      loop();
  }, 2000); // необходимая задержка
})();

В приведенном выше фрагменте объявлена именованная функция loop(), которая немедленно выполняется, эта функция рекурсивно вызывается внутри метода setTimeout() после завершения выполнения логики. Хотя этот шаблон и не гарантирует выполнение на фиксированном интервале, но он гарантирует, что предыдущий интервал был завершен до рекурсии.

JavaScript WindowOrWorkerGlobalScope
×

Кажется, вы используете блокировщик рекламы :(

Этот ресурс не является коммерческим проектом и развивается на энтузиазме автора сайта, который посвящает все свое свободное время этому проекту.

Добавьте, пожалуйста, basicweb.ru в исключения блокировщика рекламы, этим вы поможете развитию проекта.