Existe-t-il un moyen d'effacer tous les temps morts d'une fenêtre donnée? Je suppose que les délais d'attente sont stockés quelque part dans l' window
objet, mais je n'ai pas pu le confirmer.
Toute solution multi-navigateurs est la bienvenue.
Existe-t-il un moyen d'effacer tous les temps morts d'une fenêtre donnée? Je suppose que les délais d'attente sont stockés quelque part dans l' window
objet, mais je n'ai pas pu le confirmer.
Toute solution multi-navigateurs est la bienvenue.
Réponses:
Ils ne sont pas dans l'objet window, mais ils ont des identifiants, qui (afaik) sont des entiers consécutifs.
Vous pouvez donc effacer tous les délais comme suit:
var id = window.setTimeout(function() {}, 0);
while (id--) {
window.clearTimeout(id); // will do nothing if no timeout with id is present
}
Je pense que le moyen le plus simple d'y parvenir serait de stocker tous les setTimeout
identifiants dans un seul tableau, où vous pouvez facilement les parcourir clearTimeout()
sur chacun d'eux.
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]);
}
J'ai un ajout à la réponse de Pumbaa80 qui pourrait être utile pour quelqu'un qui développe pour d'anciens IE.
Oui, tous les principaux navigateurs implémentent les identifiants de délai d'expiration sous forme d'entiers consécutifs (ce qui n'est pas requis par la spécification ). Bien que le numéro de départ diffère d'un navigateur à l'autre. Il semble qu'Opera, Safari, Chrome et IE> 8 démarre les identifiants de délai d'expiration à partir de 1, les navigateurs basés sur Gecko à partir de 2 et IE <= 8 à partir d'un nombre aléatoire enregistré comme par magie lors de l'actualisation de l'onglet. Vous pouvez le découvrir vous-même .
Tout cela signifie que dans IE <= 8, le while (lastTimeoutId--)
cycle peut s'exécuter plus de 8 chiffres et afficher le message « Un script sur cette page provoque l'exécution lente d'Internet Explorer ». Donc, si vous ne pouvez pas enregistrer tous vos identifiants de délai d'expiration ou si vous ne voulez pas remplacer window.setTimeout, vous pouvez envisager d'enregistrer le premier identifiant d'expiration sur une page et de supprimer les délais d'attente jusqu'à ce qu'il.
Exécutez le code au début du chargement de la page:
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);
};
});
Et puis effacez tous les délais d'attente qui ont probablement été définis par un code étranger tant de fois que vous le souhaitez
Que diriez-vous de stocker les identifiants de délai d'expiration dans un tableau global et de définir une méthode pour déléguer l'appel de fonction à la fenêtre.
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
}
};
Vous devez réécrire la window.setTimeout
méthode et enregistrer son ID de délai d'expiration.
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();
}
}
Placez le code ci-dessous avant tout autre script et cela créera une fonction wrapper pour l'original setTimeout
&clearTimeout
.
Une nouvelle clearTimeouts
méthode sera ajoutée à l' window
objet, ce qui permettra d'effacer tous les délais (en attente) ( lien Gist ).
D'autres réponses manquent de support complet pour d'éventuels arguments
setTimeout
pourraient recevoir.
// 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);
Par souci d'exhaustivité, je souhaitais publier une solution générale couvrant à la fois setTimeout
et setInterval
.
Il semble que les navigateurs puissent utiliser le même pool d'identifiants pour les deux, mais à partir de certaines réponses à ClearTimeout et clearInterval sont-elles identiques? , il n'est pas clair s'il est sûr de se fier clearTimeout
etclearInterval
exécuter la même fonction ou de ne travailler que sur leurs types de minuterie respectifs.
Par conséquent, lorsque l'objectif est de supprimer tous les délais et intervalles, voici une implémentation qui pourrait être légèrement plus défensive entre les implémentations lorsqu'elle ne peut pas toutes les tester:
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(){}
}
Vous pouvez l'utiliser pour effacer tous les minuteurs de la fenêtre actuelle:
clearAll(window);
Ou vous pouvez l'utiliser pour effacer tous les minuteurs dans un iframe
:
clearAll(document.querySelector("iframe").contentWindow);
J'utilise Vue avec 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
}
}
Utilisez un délai d'expiration global dont toutes vos autres fonctions dérivent la synchronisation. Cela rendra tout plus rapide et plus facile à gérer, même si cela ajoutera une certaine abstraction à votre code.
set_timeout
fonction globale? Pouvez-vous donner un exemple de code?
Nous venons de publier un package résolvant exactement ce problème.
npm install time-events-manager
Avec cela, vous pouvez afficher tous les délais et intervalles via timeoutCollection
& intervalCollection
objets. Il existe également une removeAll
fonction qui efface tous les délais / intervalles à la fois de la collection et du navigateur.
C'est très tard ... mais:
Fondamentalement, les ID setTimeout / setInterval vont dans un ordre consécutif, il suffit donc de créer une fonction de temporisation fictive pour obtenir l'ID le plus élevé, puis d'effacer l'intervalle sur tous les ID inférieurs.
const highestId = window.setTimeout(() => {
for (let i = highestId; i >= 0; i--) {
window.clearInterval(i);
}
}, 0);