Функция setInterval()
предназначена для вызова переданного ей колбека через равные промежутки времени. У неё есть две особенности:
- Сложно (а иногда попросту не возможно) заниматься отладкой такого кода из-за того, что вызовы колбека будут производиться независимо от того, в каком месте кода вы поставили точку останова. На каждый шаг отладки управление будет передаваться основному циклу, который исправно вызовет колбек о очередной раз.
- Если длительность выполнения колбека по каким-либо причинам превысит установленную задержку, то это автоматически приведёт к лавинообразному увеличению количества замыканий, «выполняемых одновременно». Колбек будет вызываться снова и снова через заданный промежуток времени, не дожидаясь завершения предыдущего вызова.
От этих проблем можно избавиться, если воспользоваться setTimeout()
. В этом случае планирование следующего вызова будет производиться только после завершения выполнения предыдущего.
/**
* @param {Function} callback
* @param {Number} delay
* @param {Object} [context]
* @return {Function}
*/
function interval(callback, delay, context) {
var start = new Date(), id;
delay = delay || 0;
context = context || this;
(function loop() {
var result = callback.call(context, new Date() - start);
if (result !== false) {
id = setTimeout(loop, delay);
}
}());
return function () {
if (id) {
clearTimeout(id);
id = 0;
}
};
}
Кроме того, мы получаем несколько способов завершить выполнение этого бесконечного цикла. interval()
возвращает функцию, с помощью которой можно прерывать следующий запланированный вызов колбека. Если колбек сам вернет значение false
, то выполнение цикла также прекратится.
function doStuff(time) {
$("body").append("<p>" + time + "</p>");
return time < 10000;
}
var cancelFn = interval(doStuff, 1000);
$("button").on("click", cancelFn);
При очередном выполнении колбека, ему в качестве параметра передается разница между текущим временем и временем вызова функции interval()
. Так легко можно синхронизироваться по времени. Ведь теперь нет гарантий того, что пятый вызов колбека будет произведен ровно через 4 секунды.