¿Hay alguna forma de borrar todos los tiempos de espera de una ventana determinada? Supongo que los tiempos de espera se almacenan en algún lugar del window
objeto, pero no puedo confirmarlo.
Cualquier solución de navegador cruzado es bienvenida.
¿Hay alguna forma de borrar todos los tiempos de espera de una ventana determinada? Supongo que los tiempos de espera se almacenan en algún lugar del window
objeto, pero no puedo confirmarlo.
Cualquier solución de navegador cruzado es bienvenida.
Respuestas:
No están en el objeto de ventana, pero tienen identificadores, que (afaik) son enteros consecutivos.
Por lo tanto, puede borrar todos los tiempos de espera de esta manera:
var id = window.setTimeout(function() {}, 0);
while (id--) {
window.clearTimeout(id); // will do nothing if no timeout with id is present
}
Creo que la forma más fácil de lograr esto sería almacenar todos los setTimeout
identificadores en una matriz, donde puede iterar fácilmente clearTimeout()
en todos ellos.
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]);
}
Tengo una adición a la respuesta de Pumbaa80 que podría ser útil para alguien que esté desarrollando para IEs antiguas.
Sí, todos los navegadores principales implementan identificadores de tiempo de espera como enteros consecutivos (lo cual no es requerido por la especificación ). Aunque el número inicial difiere de un navegador a otro. Parece que Opera, Safari, Chrome e IE> 8 inician identificadores de tiempo de espera de 1, navegadores basados en Gecko de 2 e IE <= 8 de algún número aleatorio que se guarda mágicamente en la actualización de pestañas. Puedes descubrirlo tú mismo .
Todo eso significa que en IE <= 8 el while (lastTimeoutId--)
ciclo puede correr más de 8 dígitos y mostrar el mensaje " Un script en esta página hace que Internet Explorer se ejecute lentamente ". Entonces, si no puede guardar todos sus identificadores de tiempo de espera o no desea anular window.setTimeout , puede considerar guardar el primer identificador de tiempo de espera en una página y borrar los tiempos de espera hasta ese momento.
Ejecute el código en la carga de la página inicial:
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);
};
});
Y luego borre todos los tiempos de espera pendientes que probablemente fueron establecidos por código externo tantas veces como desee
¿Qué tal almacenar los identificadores de tiempo de espera en una matriz global y definir un método para delegar la llamada de función a la ventana.
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
}
};
Tienes que reescribir el window.setTimeout
método y guardar su ID de tiempo de espera.
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 el siguiente código antes de cualquier otro script y creará una función contenedora para el setTimeout
& original clearTimeout
.
Se clearTimeouts
agregarán nuevos métodos al window
Objeto, que permitirán borrar todos los tiempos de espera (pendientes) ( enlace Gist ).
Otras respuestas carecen de soporte completo para los posibles argumentos que
setTimeout
puedan recibir.
// 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, quería publicar una solución general que cubra tanto setTimeout
y setInterval
.
Parece que los navegadores pueden usar el mismo grupo de ID para ambos, pero de algunas de las respuestas a ¿Son clearTimeout y clearInterval iguales? , no está claro si es seguro confiar clearTimeout
y clearInterval
realizar la misma función o solo trabajar en sus respectivos tipos de temporizador.
Por lo tanto, cuando el objetivo es eliminar todos los tiempos de espera e intervalos, aquí hay una implementación que podría ser un poco más defensiva en todas las implementaciones cuando no se pueden probar todas:
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(){}
}
Puede usarlo para borrar todos los temporizadores en la ventana actual:
clearAll(window);
O puede usarlo para borrar todos los temporizadores en un iframe
:
clearAll(document.querySelector("iframe").contentWindow);
Yo uso Vue con 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
}
}
Utilice un tiempo de espera global del que derivan todas sus otras funciones. Esto hará que todo se ejecute más rápido y sea más fácil de administrar, aunque agregará algo de abstracción a su código.
set_timeout
función global? ¿Podría darnos un código de ejemplo?
Acabamos de publicar un paquete que resuelve este problema exacto.
npm install time-events-manager
Con eso, puede ver todos los tiempos de espera e intervalos a través de timeoutCollection
& intervalCollection
objetos. También hay una removeAll
función que borra todos los tiempos de espera / intervalos tanto de la colección como del navegador.
Esto es muy tarde ... pero:
Básicamente, los ID de setTimeout / setInterval van en orden consecutivo, así que simplemente cree una función de tiempo de espera ficticio para obtener el ID más alto, luego borre el intervalo en todos los ID inferiores a ese.
const highestId = window.setTimeout(() => {
for (let i = highestId; i >= 0; i--) {
window.clearInterval(i);
}
}, 0);