Я работаю над веб-приложением ajax, которое содержит множество тайм-аутов и интервалов. И теперь мне нужно очищать все промежутки времени и интервалы времени. Есть ли простой способ остановить все без необходимости хранить каждый тайм-аут и идентификатор интервала, итерации через них и очистить их?
Как остановить все таймауты и интервалы с помощью javascript?
Ответ 1
Обновленный ответ после прочтения дубликата я закрыл этот вопрос с помощью
Он работает и протестирован в Chrome на OSX
// run something
var id1 = setInterval(function() { console.log("interval", new Date())}, 1000);
var id2 = setTimeout(function() { console.log("timeout 1", new Date())}, 2000);
var id3 = setTimeout(function() { console.log("timeout 2", new Date())}, 5000); // not run
setTimeout(function() { console.log("timeout 3", new Date())}, 6000); // not run
// this will kill all intervals and timeouts too in 3 seconds.
// Change 3000 to anything larger than 10
var killId = setTimeout(function() {
for (var i = killId; i > 0; i--) clearInterval(i)
}, 3000);
console.log(id1, id2, id3, killId); // the IDs set by the function I used
Ответ 2
Иногда можно сохранить таймер Id/Handle, чтобы очистить его позже, что было бы лучшим решением. Так что это второе место. Но я хотел лучше понять, что происходит. Он в основном захватывает самый высокий идентификатор таймера и очищает все, что меньше. Но также можно очистить другие таймеры, которые вы не хотите очищать!
Это немного хаки, поэтому будьте осторожны!
// Set a fake timeout to get the highest timeout id
var highestTimeoutId = setTimeout(";");
for (var i = 0 ; i < highestTimeoutId ; i++) {
clearTimeout(i);
}
Ответ 3
Вот обходной путь.
window.timeoutList = new Array();
window.intervalList = new Array();
window.oldSetTimeout = window.setTimeout;
window.oldSetInterval = window.setInterval;
window.oldClearTimeout = window.clearTimeout;
window.oldClearInterval = window.clearInterval;
window.setTimeout = function(code, delay) {
var retval = window.oldSetTimeout(code, delay);
window.timeoutList.push(retval);
return retval;
};
window.clearTimeout = function(id) {
var ind = window.timeoutList.indexOf(id);
if(ind >= 0) {
window.timeoutList.splice(ind, 1);
}
var retval = window.oldClearTimeout(id);
return retval;
};
window.setInterval = function(code, delay) {
var retval = window.oldSetInterval(code, delay);
window.intervalList.push(retval);
return retval;
};
window.clearInterval = function(id) {
var ind = window.intervalList.indexOf(id);
if(ind >= 0) {
window.intervalList.splice(ind, 1);
}
var retval = window.oldClearInterval(id);
return retval;
};
window.clearAllTimeouts = function() {
for(var i in window.timeoutList) {
window.oldClearTimeout(window.timeoutList[i]);
}
window.timeoutList = new Array();
};
window.clearAllIntervals = function() {
for(var i in window.intervalList) {
window.oldClearInterval(window.intervalList[i]);
}
window.intervalList = new Array();
};
Он работает для функций set/clear timeout/interval, вызванных после выполнения этих строк. Попробуйте и посмотрите, как это работает:
setInterval('console.log(\'a\')', 1000);
setInterval('console.log(\'b\')', 500);
setInterval('console.log(\'c\')', 750);
setTimeout('clearAllIntervals()', 10000);
Проксирование делает магию.
Ответ 4
var noofTimeOuts = setTimeout('');
for (var i = 0 ; i < noofTimeOuts ; i++) clearTimeout(i);
Ответ 5
for (var i = 1; i < 99999; i++) {
window.clearInterval(i);
window.clearTimeout(i);
if(window.mozCancelAnimationFrame)window.mozCancelAnimationFrame(i); // Firefox
}
Ответ 6
Нет ничего встроенного, но довольно легко взорвать все текущие невыполненные функции выполнения отсрочки, вызвав эту функцию clearAll()
:
function clearAll() {
for (var i = setTimeout(function() {}, 0); i > 0; i--) {
window.clearInterval(i);
window.clearTimeout(i);
if (window.cancelAnimationFrame) window.cancelAnimationFrame(i);
}
}
Если вы отвечаете за запустившуюся страницу и можете обернуть собственные функции отложенного выполнения в оболочках, которые делают дом, чтобы, конечно же, оснастить каждую функцию setter соответствующим .clearAll()
:
(function(deferFunctions) {
for (var setter in deferFunctions) (function(setter, clearer) {
var ids = [];
var startFn = window[setter];
var clearFn = window[clearer];
function clear(id) {
var index = ids.indexOf(id);
if (index !== -1) ids.splice(index, 1);
return clearFn.apply(window, arguments);
}
function set() {
var id = startFn.apply(window, arguments);
ids.push(id);
return id;
}
set.clearAll = function() { ids.slice(0).forEach(clear); };
if (startFn && clearFn) {
window[setter] = set;
window[clearer] = clear;
}
})(setter, deferFunctions[setter]);
})(
{ setTimeout: 'clearTimeout'
, setInterval: 'clearInterval'
, requestAnimationFrame: 'cancelAnimationFrame'
});
Чтобы попробовать, чтобы это сработало, вы могли бы попытаться сделать это, например, который будет оставаться тихим, поскольку ни один из обратных вызовов не запускается, прежде чем они будут отменены снова:
// Some example timers of all types:
requestAnimationFrame(console.error);
setInterval(console.info, 1000, 'interval');
setTimeout(alert, 0, 'timeout');
// Now you can clear all deferred functions
// by execution type, whenever you want to:
window.setTimeout.clearAll();
window.setInterval.clearAll();
window.requestAnimationFrame.clearAll();
Ответ 7
Маленький взлом добавлен в Ответ Гохана Озтурка
Если вы используете сторонние библиотеки, которые используют Timeouts
и Intervals
, тогда они также будут очищены, поэтому я добавил один параметр для уведомления функции, что этот интервал должен быть push
'ed или not to array.
window.setTimeout = function(code, delay, toBeAdded) {
var retval = window.oldSetTimeout(code, delay);
var toBeAdded = toBeAdded || false;
if(toBeAdded) {
window.timeoutList.push(retval);
}
return retval;
};
... // likewise for all functions.
Ответ 8
Возможно, вам лучше создать планировщик. Взгляните на этот подход Надера Зейда:
https://www.onsip.com/blog/avoiding-javascript-settimeout-and-setinterval-problems
Это подход, который помогает создать определенную определенность (потому что "аргумент временного интервала каждой из этих функций действительно только устанавливает, что данная функция будет выполняться по крайней мере в течение такого количества времени. Таким образом, время события может пропустить свою цель буквально любое количество времени." ).
В частности, к вопросу, который вы задаете здесь, вы можете легко добавлять и удалять функции из очереди. Хотя этот ответ длится после того, как вопрос поднят, мы надеемся, что это будет полезно для тех, кто сталкивается с таймаутами и интервалами.
Ответ 9
Вы не можете очистить тайм-ауты и интервалы, о которых вы не знаете.
Вам понадобится что-то вроде getTimeoutList
, которое не входит в спецификацию DOM3 или даже запланировано, AFAIK.
Ответ 10
Предыдущий прокси-трюк хорош, но если у вас много тайм-аутов и интервалов, я бы не заполнил массивы последовательными номерами [1,2,3....]
, но с интервалами. Например, вместо [1,2,3,7,8,9]
у вас может быть что-то вроде ['1-3','7-9']
или [[1,3],[7,9]]
, как оптимизация памяти. Конечно, этот трюк подходит только в том случае, если у вас много тайм-аутов и интервалов, а также если вы не остановите часто используемые интервалы.