特定のウィンドウからすべてのタイムアウトをクリアする方法はありますか?タイムアウトはwindow
オブジェクトのどこかに格納されていると思いますが、確認できませんでした。
クロスブラウザーソリューションは大歓迎です。
特定のウィンドウからすべてのタイムアウトをクリアする方法はありますか?タイムアウトはwindow
オブジェクトのどこかに格納されていると思いますが、確認できませんでした。
クロスブラウザーソリューションは大歓迎です。
回答:
それらはウィンドウオブジェクトにはありませんが、IDを持っています。これは連続した整数です(afaik)。
したがって、次のようにすべてのタイムアウトをクリアできます。
var id = window.setTimeout(function() {}, 0);
while (id--) {
window.clearTimeout(id); // will do nothing if no timeout with id is present
}
これを達成する最も簡単な方法は、すべての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]);
}
私はPumbaa80の回答に加えて、古いIE向けに開発している人に役立つかもしれません。
はい、すべての主要なブラウザーはタイムアウトIDを連続した整数として実装しています(仕様では必須ではありません)。開始番号はブラウザによって異なります。Opera、Safari、Chrome、IE> 8は1からタイムアウトIDを開始し、Geckoベースのブラウザーは2から、IE <= 8はタブの更新時に魔法のように保存された乱数から開始しているようです。自分で発見できる。
つまり、IEで8以下のwhile (lastTimeoutId--)
サイクルが8 桁以上実行され、「このページのスクリプトが原因で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);
};
});
そして、おそらく外部コードによって設定された保留タイムアウトをすべてクリアします
タイムアウト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
}
};
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();
}
}
以下のコードを他のスクリプトの前に配置すると、元のsetTimeout
&のラッパー関数が作成されますclearTimeout
。
新しいclearTimeouts
メソッドがwindow
オブジェクトに追加され、すべての(保留中の)タイムアウトをクリアできるようになります(Gistリンク)。
他の回答は、受け取られる可能性のある議論に対する完全なサポートを欠いています。
setTimeout
// 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);
完全を期すために、私は一般的な解決策を投稿したいとカバーの両方setTimeout
とsetInterval
。
ブラウザは両方に同じIDのプールを使用しているようですが、いくつかの回答から、Are 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);
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
}
}
この正確な問題を解決するパッケージを公開しました。
npm install time-events-manager
これにより、timeoutCollection
&intervalCollection
オブジェクトを介してすべてのタイムアウトと間隔を表示できます。removeAll
コレクションとブラウザの両方からすべてのタイムアウト/間隔をクリアする関数もあります。