Existe uma maneira de limpar todos os tempos limite de uma determinada janela? Suponho que os tempos limites estejam armazenados em algum lugar do window
objeto, mas não foi possível confirmar isso.
Qualquer solução cross-browser é bem-vinda.
Existe uma maneira de limpar todos os tempos limite de uma determinada janela? Suponho que os tempos limites estejam armazenados em algum lugar do window
objeto, mas não foi possível confirmar isso.
Qualquer solução cross-browser é bem-vinda.
Respostas:
Eles não estão no objeto janela, mas têm ids, que (afaik) são inteiros consecutivos.
Portanto, você pode limpar todos os tempos limite como:
var id = window.setTimeout(function() {}, 0);
while (id--) {
window.clearTimeout(id); // will do nothing if no timeout with id is present
}
Acho que a maneira mais fácil de fazer isso seria armazenar todos os setTimeout
identificadores em um array, onde você pode iterar facilmente clearTimeout()
em todos eles.
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]);
}
Eu tenho uma adição à resposta do Pumbaa80 que pode ser útil para alguém desenvolvendo para IEs antigos.
Sim, todos os principais navegadores implementam ids de tempo limite como inteiros consecutivos (o que não é exigido pela especificação ). Embora o número inicial seja diferente de navegador para navegador. Parece que Opera, Safari, Chrome e IE> 8 iniciam ids de tempo limite de 1, navegadores baseados no Gecko de 2 e IE <= 8 de algum número aleatório que é salvo magicamente na atualização da guia. Você pode descobrir sozinho .
Tudo isso indica que no IE <= 8 o while (lastTimeoutId--)
ciclo pode ser executado mais de 8 dígitos e mostrar a mensagem " Um script nesta página está fazendo com que o Internet Explorer seja executado lentamente ". Portanto, se você não puder salvar todos os ids de timeout ou não quiser substituir window.setTimeout, você pode considerar salvar o primeiro id de timeout em uma página e limpar os tempos limites até ele.
Execute o código no carregamento inicial da página:
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);
};
});
E, em seguida, limpe todos os tempos limite pendentes que provavelmente foram definidos por código estrangeiro tantas vezes que você deseja
Que tal armazenar os ids de tempo limite em uma matriz global e definir um método para delegar a chamada de função para a janela.
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
}
};
Você deve reescrever o window.setTimeout
método e salvar seu ID de tempo limite.
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();
}
}
Coloque o código abaixo antes de qualquer outro script e ele criará uma função de wrapper para o setTimeout
& original clearTimeout
.
Um novo clearTimeouts
método será adicionado ao window
objeto, o que permitirá limpar todos os tempos limite (pendentes) ( link Gist ).
Outras respostas não têm suporte completo para possíveis argumentos
setTimeout
podem receber.
// 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, arg ){
// also, wrap the callback, so the cache reference will be removed
// when the timeout has reached (fired the callback)
var id = _set(function(){
CB.apply(null, arguments)
removeCacheItem(id)
}, duration || 0, arg)
cache.push( id ) // store reference in the cache array
// id reference must be returned to be able to clear it
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(){
console.log("Clearing " + cache.length + " timeouts")
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);
Para completar, gostaria de postar uma solução geral que abrange ambos setTimeout
e setInterval
.
Parece que os navegadores podem usar o mesmo pool de IDs para ambos, mas de algumas das respostas para ClearTimeout e clearInterval o mesmo? , não está claro se é seguro confiar clearTimeout
e clearInterval
executar a mesma função ou apenas trabalhar em seus respectivos tipos de temporizador.
Portanto, quando o objetivo é eliminar todos os tempos limite e intervalos, aqui está uma implementação que pode ser um pouco mais defensiva entre as implementações quando não é possível testar todos eles:
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(){}
}
Você pode usá-lo para limpar todos os temporizadores na janela atual:
clearAll(window);
Ou você pode usá-lo para limpar todos os temporizadores em um iframe
:
clearAll(document.querySelector("iframe").contentWindow);
Eu uso Vue com 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
}
}
Use um tempo limite global do qual todas as outras funções derivam do tempo. Isso fará com que tudo seja executado mais rápido e mais fácil de gerenciar, embora adicione alguma abstração ao seu código.
set_timeout
função global? Você poderia dar um exemplo de código?
Acabamos de publicar um pacote que resolve exatamente esse problema.
npm install time-events-manager
Com isso, você pode ver todos os tempos limite e intervalos por meio de timeoutCollection
& intervalCollection
objetos. Há também uma removeAll
função que limpa todos os tempos limite / intervalos da coleção e do navegador.
Já é muito tarde ... mas:
Basicamente, os IDs setTimeout / setInterval vão em ordem consecutiva, portanto, basta criar uma função de tempo limite fictício para obter o ID mais alto e limpar o intervalo em todos os IDs menores que esse.
const highestId = window.setTimeout(() => {
for (let i = highestId; i >= 0; i--) {
window.clearInterval(i);
}
}, 0);