web-dev-qa-db-ja.com

javascript:すべてのタイムアウトをクリアしますか?

特定のウィンドウからすべてのタイムアウトをクリアする方法はありますか?タイムアウトはwindowオブジェクトのどこかに保存されていると思いますが、それを確認できませんでした。

任意のクロスブラウザソリューションを歓迎します。

82
marcio

これらはウィンドウオブジェクトにはありませんが、IDがあります(これは連続した整数です)。

そのため、次のようにすべてのタイムアウトをクリアできます。

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

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

これを達成する最も簡単な方法は、すべてのsetTimeout識別子を1つの配列に格納することだと思います。すべての識別子に対してclearTimeout()を簡単に反復処理できます。

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]);
}
72

Pumbaa80's answer に追加があります。これは、古いIE向けに開発している人に役立つかもしれません。

はい、すべての主要なブラウザはタイムアウトIDを連続した整数として実装しています(これは 仕様では必要ありません です)。開始番号を通して、ブラウザごとに形式が異なります。 Opera、Safari、Chrome and IE> 8は、1からタイムアウトIDを開始し、2からGeckoベースのブラウザとIE <= 8は、タブの更新時に魔法のように保存された乱数から取得します。 自分で発見 できます。

IE <= 8 while (lastTimeoutId--)サイクルが8桁以上実行され、このページに「Aスクリプトを表示する」 Internet Explorerの実行速度が遅い」というメッセージが表示されるため、 タイムアウトIDをすべて保存 できない場合、または window.setTimeoutを上書きしたくない場合) ページの最初のタイムアウトIDを保存し、それまでタイムアウトをクリアすることを検討できます。

ページの初期読み込み時にコードを実行します。

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);
    };
});

そして、おそらく外国のコードによって何度も設定されたすべての保留中のタイムアウトをクリアします

11
Kolya Ay

タイムアウトIDをグローバル配列に保存し、ウィンドウに関数呼び出しを委任するメソッドを定義する方法はどうでしょう。

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
    }
};
9
Jaskey

window.setTimeoutメソッドを書き換えて、タイムアウトIDを保存する必要があります。

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

既存のコードを変更せずに、以下のコードを他の何かの前に配置すると、元のsetTimeoutのラッパー関数が作成されます。 &clearTimeoutそして、新しいものを追加しますclearTimeoutsは、タイムアウトをクリアallGist link

// 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

この問題を解決するパッケージを公開しました。

npm install time-events-manager

これにより、timeoutCollectionおよびintervalCollectionオブジェクトを介してすべてのタイムアウトと間隔を表示できます。コレクションとブラウザの両方からすべてのタイムアウト/間隔をクリアするremoveAll関数もあります。

0
Bar Goldinfeld

完全を期すために、setTimeoutsetIntervalの両方をカバーする一般的なソリューションを投稿したかった。

ブラウザは両方に同じIDプールを使用するようですが、 clearTimeoutとclearIntervalは同じですか? に対する回答のいくつかから、clearTimeoutに依存しても安全かどうかは明確ではありませんおよびclearIntervalは、同じ機能を実行するか、それぞれのタイマータイプでのみ動作します。

したがって、目標がすべてのタイムアウトと間隔を強制終了することである場合、すべてをテストできない場合に実装全体で少し防御的となる可能性がある実装を次に示します。

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(){}
}

これを使用して、現在のウィンドウのすべてのタイマーをクリアできます。

clearAll(window);

または、iframe内のすべてのタイマーをクリアするために使用できます:

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

他のすべての関数がタイミングを導出するグローバルタイムアウトを使用します。これにより、コードが抽象化されますが、すべてが高速に実行され、管理が容易になります。

0
Travis J

TypeScriptでVueを使用します。

    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