Как остановить все таймауты и интервалы с помощью javascript?

Я работаю над веб-приложением ajax, которое содержит множество тайм-аутов и интервалов. И теперь мне нужно очищать все промежутки времени и интервалы времени. Есть ли простой способ остановить все без необходимости хранить каждый тайм-аут и идентификатор интервала, итерации через них и очистить их?

Ответ 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]], как оптимизация памяти. Конечно, этот трюк подходит только в том случае, если у вас много тайм-аутов и интервалов, а также если вы не остановите часто используемые интервалы.