Мы можем вызвать функцию не в данный момент, а позже, через заданный интервал времени. Это называется «планирование вызова».
Для этого существуют два метода:
- setTimeout позволяет вызвать функцию один раз через определённый интервал времени.
- setInterval позволяет вызывать функцию регулярно, повторяя вызов через определённый интервал времени.
setTimeout
Синтаксис: let timerId = setTimeout(func|code, [delay], [arg1], [arg2], ...);
Параметры:
func|code
Функция или строка кода для выполнения. Обычно это функция. По историческим причинам можно передать и строку кода, но это не рекомендуется.
delay
Задержка перед запуском в миллисекундах (1000 мс = 1 с). Значение по умолчанию – 0.
arg1
, arg2
… Аргументы, передаваемые в функцию
Например, данный код вызывает sayHi()
спустя одну секунду:
function sayHi() {
alert("Привет")
}
setTimeout(sayHi, 1000)
С аргументами:
function sayHi(phrase, who) {
alert(phrase + ", " + who)
}
_
setTimeout(sayHi, 1000, "Привет", "Джон") // Привет, Джон_`
Если первый аргумент является строкой, то JavaScript создаст из неё функцию.
setInterval
Метод setInterval
имеет такой же синтаксис как setTimeout
:
let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...);
Все аргументы имеют такое же значение. Но отличие этого метода от setTimeout
в том, что функция запускается не один раз, а периодически через указанный интервал времени.
Рекурсивный setTimeout
Применение вложенного setTimeout
:
let i = 1
setTimeout(function run() {
func(i)
setTimeout(run, 100)
}, 100)
Ниже представлено изображение, показывающее процесс работы рекурсивного setTimeout
:
ВложенныйsetTimeout
гарантирует фиксированную задержку (здесь 100 мс).
Это потому, что новый вызов планируется в конце предыдущего.
Отличие setInterval и рекурсивного setTimeout
Применение setInterval
:
let i = 1;
setInterval(function() {
func(i); }, 100);`
Для setInterval
внутренний планировщик будет выполнять func(i)
каждые 100 мс:
Реальная задержка между вызовами
func
с помощью setInterval
меньше, чем указано в коде!
Это нормально, потому что время, затраченное на выполнение func
, использует часть заданного интервала времени.
Вполне возможно, что выполнение func
будет дольше, чем мы ожидали, и займёт более 100 мс.
В данном случае движок ждёт окончания выполнения func
и затем проверяет планировщик и, если время истекло, немедленно запускает его снова.
Как отменять таймеры и зачем это нужно?
Вызов setTimeout
возвращает «идентификатор таймера» timerId
, который можно использовать для отмены дальнейшего выполнения.
Синтаксис для отмены:
let timerId = setTimeout(...); clearTimeout(timerId);
В коде ниже планируем вызов функции и затем отменяем его (просто передумали). В результате ничего не происходит:
let timerId = setTimeout(() => alert("ничего не происходит"), 1000)
alert(timerId) // идентификатор таймера
clearTimeout(timerId)
alert(timerId) // тот же идентификатор (не принимает значение null после отмены)`
Как мы видим из вывода alert
, в браузере идентификатором таймера является число. В других средах это может быть что-то ещё. Например, Node.js возвращает объект таймера с дополнительными методами.
Повторюсь, что нет единой спецификации на эти методы, поэтому такое поведение является нормальным.
Для браузеров таймеры описаны в разделе таймеров стандарта HTML5.