Как очистить интервал с неизвестным идентификатором?

Скажем, кто-то (зло) установил нам таймер с setInterval, но мы не знаем его ID (у нас нет ни ссылки на объект, который возвращает setInterval, ни его значения)

(function(){
  setInterval(function(){console.log('pwned')},
              10000)
})();

Есть ли способ, как его очистить? Можно ли получить доступ к таймеру каким-то другим способом? Или, по крайней мере, в конкретном браузере/движке javascript?

Дэвид Флэнаган затрагивает аналогичную тему в своем большом JSTDG. Ключ setInterval() method, use in malicious code в указателе указывает на

... Некоторые браузеры обнаруживают повторяющиеся диалоговые окна и длительные сценарии и дают пользователю возможность остановить их. Но вредоносный код может использовать такие методы, как setInterval(), для загрузки ЦП, а также может атаковать вашу систему, выделяя много памяти. Не существует общего способа, с помощью которого веб-браузеры могли бы предотвратить такого рода неуклюжие атаки. На практике это не является распространенной проблемой в Интернете, поскольку никто не возвращается на сайт, который занимается подобным злоупотреблением сценариями!


person mykhal    schedule 27.07.2011    source источник
comment
Связано - stackoverflow.com/questions/3141064/   -  person Shadow Wizard Wearing Mask V2    schedule 27.07.2011
comment
Хм.. еще одна идея - случайно они не дают функции имя?   -  person Shadow Wizard Wearing Mask V2    schedule 27.07.2011
comment
Shadow Wizard, в данном случае, к сожалению, был установлен в закрытии (что иногда считается хорошей функцией для использования в целях безопасности).. я знаю, этот вопрос несколько теоретический, потому что мы, вероятно, можем в большинстве случаев найти и отредактировать неприятный код локально в некоторых браузерах   -  person mykhal    schedule 27.07.2011
comment
Shadow Wizard... эээ, может быть, это не совсем закрытие. но это анонимная функция, которая была выполнена. наличие ссылки на функцию поможет нам как-то?   -  person mykhal    schedule 27.07.2011
comment
да, вы можете (по крайней мере теоретически) переопределить функцию и поместить свою собственную функцию со своим собственным кодом. Функция, объявленная последней с тем же именем, будет выполняться во время выполнения.   -  person Shadow Wizard Wearing Mask V2    schedule 27.07.2011


Ответы (4)


Из быстрого теста все основные браузеры (последние версии Chrome, Firefox и IE) дают довольно маленькие числа в качестве идентификатора, поэтому просто «слепой» цикл по всем возможным числам должен работать нормально:

function ClearAllIntervals() {
    for (var i = 1; i < 99999; i++)
        window.clearInterval(i);
}

Полный пример:

window.onload = function() {
    window.setInterval(function() {
        document.getElementById("Tick").innerHTML += "tick<br />";
    }, 1000);
    window.setInterval(function() {
        document.getElementById("Tack").innerHTML += "tack<br />";
    }, 1000);
};

function ClearAllIntervals() {
    for (var i = 1; i < 99999; i++)
        window.clearInterval(i);
}
#Placeholder div { width: 80px; float: left; }
<button type="button" onclick="ClearAllIntervals();">Clear All</button>
<div id="Placeholder">
    <div id="Tick"></div>
    <div id="Tack"></div>
</div>

Это остановит все интервалы, не может остановить определенный интервал, не зная его ID, конечно.

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

person Shadow Wizard Wearing Mask V2    schedule 27.07.2011
comment
также см. мой комментарий под ответом Ханса Б. Пуфала :) - person mykhal; 27.07.2011
comment
Что ж, мой способ будет работать, даже если в разных точках кода активировано много интервалов, однако очевидно, что способ Ганса более элегантен и эффективен. - person Shadow Wizard Wearing Mask V2; 27.07.2011
comment
Немного поздно для вечеринки. Следует отметить, что setInterval и setTimeout используют один и тот же пул идентификаторов, поэтому это также отменит любые setTimeout. - person kristiyan.mitev; 17.07.2019

Что ж, эмпирические испытания в Chrome показывают, что setInterval возвращает число, которое увеличивается при каждом вызове. Поэтому, если вы УВЕРЕНЫ, что setInterval был последним установленным, будет работать следующее:

function clearLastInterval () {
  var i = setInterval (function () {}, 10000);
  clearInterval (i-1);
  clearInterval (i);
}

Я не уверен, что буду рекомендовать это, хотя ;-)

person HBP    schedule 27.07.2011
comment
это возможный способ :) что-то вроде pauseInterval было бы полезно для ручного поиска правильного таймера, так как мы не хотим убивать невинных.. - person mykhal; 27.07.2011

Я попробовал подход, предложенный #Shadow Wizard, и он сработал при очистке интервала. Однако впоследствии этот подход имел побочные эффекты. В моем конкретном случае я не смог использовать jquery.fadeTo() после очистки всех интервалов.

Подход, на котором я остановился, является более чистым решением, которое заключается в переопределении метода setInterval и сохранении идентификаторов интервалов в переопределенных методах. Как показано здесь, я помещаю идентификаторы в массив, а затем очищаю их все. Немного уточнив структуру хранения массивов, вы можете пометить их и выборочно очистить.

var intervalTracking = new Array();
var intervalCount=0;

window.oldSetInterval = window.setInterval;
window.setInterval = ( function(func, interval) {
    var interval = oldSetInterval(func, interval);
    intervalTracking[++intervalCount]=interval;
    return interval;
});

function clearAllIntervals() {
    for (var i = 0 ; i <= intervalCount ; i++) {
    window.clearInterval( intervalTracking[i] );
    }
}

Кажется, это работает!

person Mark Chackerian    schedule 05.10.2011

Я решил это, используя localstorage, сохранив там идентификатор setInterval и забрав его позже, чтобы очистить этот интервал.

person Daniel Garcia Sanchez    schedule 11.09.2015