web-dev-qa-db-fra.com

javascript: effacer tous les délais d'attente?

Existe-t-il un moyen de supprimer tous les délais d'une fenêtre donnée? Je suppose que les délais d'attente sont stockés quelque part dans l'objet window mais ne peuvent pas le confirmer.

Toute solution multi-navigateur est la bienvenue.

75
marcio

Ils ne sont pas dans l'objet window, mais ils ont des identifiants qui (autant que possible) sont des entiers consécutifs.

Vous pouvez donc effacer tous les délais d'attente de la manière suivante:

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

while (id--) {
    window.clearTimeout(id); // will do nothing if no timeout with id is present
}
110
user123444555621

Je pense que le moyen le plus simple d'y parvenir serait de stocker tous les identifiants setTimeout dans un tableau, où vous pourrez facilement effectuer une itération sur 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]);
}
69
Michael Berkowski

J'ai un ajout à réponse de Pumbaa80 qui pourrait être utile pour quelqu'un qui développe pour de vieux IE. 

Oui, tous les principaux navigateurs implémentent les identifiants de délai d'expiration sous forme d'entiers consécutifs (c'est-à-dire non requis par la spécification ). Bien que le numéro de départ diffère formulaire de navigateur en navigateur. Il semble qu'Opera, Safari, Chrome et IE> 8 lancent 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 qui est sauvegardé de manière magique lors de l'actualisation des onglets. Vous pouvez le découvrir vous-même .

Tout cela signifie que dans le cycle IE <= 8, le cycle while (lastTimeoutId--) peut s'exécuter plus de 8 chiffres et afficher le message "Un script sur cette page provoque l'exécution lente de" d'Internet Explorer. Donc, si vous ne pouvez pas enregistrer tous vos identifiants de délai d'expiration ou ne voulez pas remplacer window.setTimeout , vous pouvez envisager de sauvegarder le premier identifiant de délai d'expiration sur une page et de supprimer les dépassements de délai.

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 effacez tous les délais d'attente en attente qui ont probablement été définis par le code étranger autant de fois que vous le souhaitez.

11
Kolya Ay

Pourquoi ne pas stocker les identifiants de délai d’attente dans un tableau global et 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
    }
};
6
Jaskey

Sans changer aucun code existant, vous pouvez placer le code ci-dessous avant et créer un fonctions d'encapsulation pour les setTimeout & clearTimeout d'origine et en ajouter un nouveau clearTimeouts qui effacera tout les délais ( lien 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);
1
vsync

Vous devez réécrire la méthode window.setTimeout et enregistrer son ID de délai d'attente.

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();
  }
}
0
guest

Nous venons de publier un paquet résolvant ce problème précis.

npm install time-events-manager

Avec cela, vous pouvez afficher tous les délais et intervalles avec les objets timeoutCollection & intervalCollection . Il existe également une fonction removeAll qui efface tous les délais/intervalles de la collection et du navigateur.

0
Bar Goldinfeld

Pour être complet, je souhaitais publier une solution générale couvrant à la fois setTimeout et setInterval.

Il semble que les navigateurs utilisent le même pool d'ID pour les deux, mais certaines réponses à clearTimeout et clearInterval sont-elles identiques? , il n'est pas clair s'il est prudent de compter sur clearTimeout et clearInterval pour exécuter la même fonction ou pour ne travailler que sur leurs types de minuteur respectifs.

Par conséquent, lorsque l'objectif est d'éliminer tous les délais d'attente et tous les intervalles, voici une implémentation qui pourrait être légèrement plus défensive à travers les implémentations si elle est incapable de 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 toutes les minuteries de la fenêtre en cours:

clearAll(window);

Ou vous pouvez l’utiliser pour effacer toutes les minuteries dans une iframe:

clearAll(document.querySelector("iframe").contentWindow);
0
Chris Calo

Utilisez un délai d'expiration global dont toutes les autres fonctions dérivent du minutage. Cela accélérera l'exécution et facilitera la gestion, même si cela ajoutera une certaine abstraction à votre code.

0
Travis J

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
        }
    }
0
user3010152