JavaScript: очистить все таймауты? - PullRequest
80 голосов
/ 14 января 2012

Есть ли способ очистить все тайм-ауты из данного окна? Я предполагаю, что тайм-ауты хранятся где-то в window объекте, но не могут подтвердить это.

Любое кросс-браузерное решение приветствуется.

Ответы [ 10 ]

113 голосов
/ 14 января 2012

Они не находятся в объекте окна, но имеют идентификаторы, которые (afaik) являются последовательными целыми числами.

Таким образом, вы можете очистить все таймауты следующим образом:

var id = window.setTimeout(function() {}, 0);

while (id--) {
    window.clearTimeout(id); // will do nothing if no timeout with id is present
}
71 голосов
/ 14 января 2012

Я думаю, что самый простой способ сделать это - хранить все setTimeout идентификаторы в одном массиве, где вы можете легко перебрать clearTimeout() на всех них.

var timeouts = [];
timeouts.push(setTimeout(function(){alert(1);}, 200));
timeouts.push(setTimeout(function(){alert(2);}, 300));
timeouts.push(setTimeout(function(){alert(3);}, 400));

for (var i=0; i<timeouts.length; i++) {
  clearTimeout(timeouts[i]);
}
11 голосов
/ 08 мая 2013

У меня есть дополнение к ответу Pumbaa80 , которое может быть полезно для тех, кто разрабатывает для старых IE.

Да, все основные браузеры реализуют идентификаторы тайм-аута в виде последовательных целых чисел (что не требуется согласно спецификации ).Начиная стартовый номер отличается от браузера к браузеру.Похоже, что Opera, Safari, Chrome и IE> 8 запускают идентификаторы тайм-аута с 1, браузеры на основе Gecko с 2 и IE <= 8 с некоторого случайного числа, которое волшебным образом сохраняется при обновлении вкладки.Вы можете <a href="http://plnkr.co/edit/prHh97?p=preview" rel="nofollow noreferrer"> обнаружить его самостоятельно .

Все это означает, что в IE <= 8 цикл <code>while (lastTimeoutId--) может выполняться более 8 раз и отображать сценарий "" на этой странице:в результате чего Internet Explorer работает медленно"сообщение.Поэтому, если вы не можете сохранить все свои идентификаторы тайм-аута или не хотите переопределить window.setTimeout , вы можете сохранить первый идентификатор тайм-аута на странице и очистить тайм-ауты до него.

Выполнить код при ранней загрузке страницы:

var clearAllTimeouts = (function () {
    var noop = function () {},
        firstId = window.setTimeout(noop, 0);
    return function () {
        var lastId = window.setTimeout(noop, 0);
        console.log('Removing', lastId - firstId, 'timeout handlers');
        while (firstId != lastId)
            window.clearTimeout(++firstId);
    };
});

и затем очистить все ожидающие таймауты, которые, вероятно, были установлены внешним кодом столько раз, сколько вам нужно

7 голосов
/ 30 марта 2015

Как насчет сохранения идентификаторов тайм-аута в глобальном массиве и определения метода для делегирования вызова функции окнам.

GLOBAL={
    timeouts : [],//global timeout id arrays
    setTimeout : function(code,number){
        this.timeouts.push(setTimeout(code,number));
    },
    clearAllTimeout :function(){
        for (var i=0; i<this.timeouts.length; i++) {
            window.clearTimeout(this.timeouts[i]); // clear all the timeouts
        }
        this.timeouts= [];//empty the id array
    }
};
1 голос
/ 23 апреля 2019

Необходимо переписать метод window.setTimeout и сохранить его идентификатор тайм-аута.

const timeouts = [];
const originalTimeoutFn = window.setTimeout;

window.setTimeout = function(fun, delay) { //this is over-writing the original method
  const t = originalTimeoutFn(fn, delay);
  timeouts.push(t);
}

function clearTimeouts(){
  while(timeouts.length){
    clearTimeout(timeouts.pop();
  }
}
1 голос
/ 24 сентября 2018

Не изменяя существующий код, вы можете поместить приведенный ниже код перед чем-либо еще, и он создаст функции-обертки для оригинального setTimeout & clearTimeout, а также добавит новый clearTimeouts который очистит все тайм-ауты ( ссылка Gist )

// isolated layer wrapper (for the local variables)
(function(_W){

var cache = [],                // will store all timeouts IDs
    _set = _W.setTimeout,      // save original reference
    _clear = _W.clearTimeout;  // save original reference

// Wrap original setTimeout with a function 
_W.setTimeout = function( CB, duration ){
    // also, wrap the callback, so the cache referece will be removed 
    // when the timerout has reached (fired the callback)
    var id = _set(function(){
        CB();
        removeCacheItem(id);
    }, duration || 0);

    cache.push( id ); // store reference in the cache array

    // id must be returned to the user could save it and clear it if they choose to
    return id ;
}

// Wrap original clearTimeout with a function 
_W.clearTimeout = function( id ){
    _clear(id);
    removeCacheItem(id);
}

// Add a custom function named "clearTimeouts" to the "window" object
_W.clearTimeouts = function(){
    cache.forEach(n => _clear(n))
    cache.length = [];
}

// removes a specific id from the cache array 
function removeCacheItem( id ){
    var idx = cache.indexOf(id);

    if( idx > -1 )
        cache = cache.filter(n => n != id )
}

})(window);
0 голосов
/ 04 февраля 2019

Я использую Vue с Typescript.

    private setTimeoutN;
    private setTimeoutS = [];

    public myTimeoutStart() {

        this.myTimeoutStop();//stop All my timeouts

        this.setTimeoutN = window.setTimeout( () => {
            console.log('setTimeout');
        }, 2000);

        this.setTimeoutS.push(this.setTimeoutN)//add THIS timeout ID in array

    }

    public myTimeoutStop() {

        if( this.setTimeoutS.length > 0 ) {
            for (let id in this.setTimeoutS) {
                console.log(this.setTimeoutS[id]);
                clearTimeout(this.setTimeoutS[id]);
            }
            this.setTimeoutS = [];//clear IDs array
        }
    }
0 голосов
/ 24 октября 2018

Для полноты картины я хотел опубликовать общее решение, которое охватывает как setTimeout, так и setInterval.

. Кажется, браузеры могут использовать один и тот же пул идентификаторов для обоих, но из некоторых ответов на Являются ли clearTimeout и clearInterval одинаковыми? , неясно, безопасно ли полагаться на clearTimeout и clearInterval, выполняющие одну и ту же функцию, или работать только с соответствующими им типами таймеров.

ПоэтомуКогда цель состоит в том, чтобы убить все тайм-ауты и интервалы, вот реализация, которая может быть немного более защищенной для всех реализаций, когда не удается протестировать их все:

function clearAll(windowObject) {
  var id = Math.max(
    windowObject.setInterval(noop, 1000),
    windowObject.setTimeout(noop, 1000)
  );

  while (id--) {
    windowObject.clearTimeout(id);
    windowObject.clearInterval(id);
  }

  function noop(){}
}

Вы можете использовать его для очистки всех таймеров втекущее окно:

clearAll(window);

Или вы можете использовать его для очистки всех таймеров в iframe:

clearAll(document.querySelector("iframe").contentWindow);
0 голосов
/ 11 мая 2017

Мы только что опубликовали пакет, решающий эту проблему.

npm install time-events-manager

При этом вы можете просматривать все тайм-ауты и интервалы с помощью timeoutCollection & intervalCollection объектов. Также имеется функция removeAll, которая очищает все таймауты / интервалы как из коллекции, так и из браузера.

0 голосов
/ 14 января 2012

Используйте глобальный тайм-аут, из которого все ваши другие функции зависят от времени.Это сделает все быстрее и проще в управлении, хотя и добавит некоторую абстракцию в ваш код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...