setTimeout
и setInterval
В JavaScript есть две функции для отложенного запуска кода: setTimeout
и setInterval
. Отличаются они тем, что setTimeout
запускает код единожды, а setInterval
— постоянно с заданной периодичностью.
Обе функции первым аргументом принимают строку кода, которую необходимо выполнить, или функцию, которую необходимо запустить. Второй аргумент задаёт задержку в миллисекундах. Возвращают обе функции идентификатор созданного таймера.
setTimeout('alert(1)', 2000); // Через две секунды выскочит сообщение
setTimeout(function() {
alert(1);
}, 2000); // то же самое, но с функцией.
Обратите внимание, что строка кода — это именно строка, заключённая в кавычки, а не просто код. Впрочем передавать строку не рекомендуется. Она выполняется в глобальной области видимости, а скрипты, как правило, находятся в какой-нибудь локальной области, в результате строка кода, передаваемая в setTimeout
/setInterval
не имеет доступа к данным и функциям скрипта. Да и неудобно это — писать код внутри строки, он даже не подсвечивается.
function f() {
var a = 1;
setTimeout('alert(a)', 2000); // Через две секунды будет ошибка,
// т.к. a не определена в глобальной области видимости.
}
function f() {
var a = 1;
setTimeout(function() {
alert(a);
}, 2000); // Через две секунды выскочит сообщение
}
Действие функций setTimeout
и setInterval
можно отменить функциями clearTimeout и clearInterval соответственно, передавая последним идентификатор отключаемого таймера.
Простой пример: при наведении мышкой на элемент необходимо через две секунды показать сообщение. Однако если в течение этих двух секунд указатель мыши был убран с элемента, то сообщение показывать не нужно.
var timerId;
element.onmouseover = function() {
timerId = setTimeout(function() {
alert(1);
}, 2000);
};
element.onmouseout = function() {
clearTimeout(timerId);
};
Если в clearTimeout
/clearInterval
передан недействительный идентификатор, то ничего не произойдёт. Поэтому в примере выше можно не проверять, отработал ли уже таймер, и что вообще лежит в timerId.
Многие начинающие в JavaScript разработчики путают принцип работы его таймеров с принципом работы имеющейся во многих языках функции sleep
. sleep
приостанавливает выполнение программы на определённый промежуток времени, после чего работа продолжается с того же места, где была остановлена. В JavaScript такое невозможно, по крайней мере в браузерном JavaScript.
JavaScript язык однопоточный. Когда он выполняется в браузере, браузер никаких действий не производит. Если скрипт выполняется достаточно долго, становится заметно, что браузер "висит". Поэтому функция sleep
вместе с приостановкой скрипта "вешала" бы браузер.
Вместо этого функции setTimeout
/setInterval
"делают отметку", что необходимо запустить некий код через столько-то миллисекунд, а скрипт продолжает работать своим чередом.
var n = 0;
setTimeout(function() {
alert(n); // На момент вывода сообщения n уже будет равна 5.
}, 1); // Ставим минимально возможный интервал
n = 5; // После установки таймера меняем значение переменной.
Из того, что язык однопоточный следует ещё одно следствие — код выполнится не через строго заданный промежуток времени, а не раньше, чем через этот промежуток. Если в нужный момент времени будет выполняться какой-либо код, то интерпретатор дождётся его окончания, после чего только запустит код по таймеру.
В Firefox функции setTimeout
и setInterval
передают своим callback-функциям один числовой параметр, равный количеству миллисекунд, на которые запоздал вызов функции.
setTimeout(function(delta) {
alert(delta); // Чем дольше будет открыто первое окно, тем большее число здесь будет.
});
alert(1);
К сожалению, в остальных браузерах данного функционала нет.
setInterval