Belirli bir pencereden tüm zaman aşımlarını temizlemenin bir yolu var mı? Sanırım zaman aşımları window
nesnede bir yerde saklanıyor, ancak bunu teyit edemedim.
Herhangi bir çapraz tarayıcı çözümü kabul edilir.
Belirli bir pencereden tüm zaman aşımlarını temizlemenin bir yolu var mı? Sanırım zaman aşımları window
nesnede bir yerde saklanıyor, ancak bunu teyit edemedim.
Herhangi bir çapraz tarayıcı çözümü kabul edilir.
Yanıtlar:
Pencere nesnesinde değillerdir, ancak (afaik) ardışık tam sayı olan kimlikleri vardır.
Böylece tüm zaman aşımlarını şu şekilde temizleyebilirsiniz:
var id = window.setTimeout(function() {}, 0);
while (id--) {
window.clearTimeout(id); // will do nothing if no timeout with id is present
}
Bence bunu başarmanın en kolay yolu, tüm setTimeout
tanımlayıcıları kolayca yineleyebileceğiniz tek bir dizide saklamaktır 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]);
}
Ben bir ekleme sahip Pumbaa80 cevabı eski IE'lerin için gelişmekte birisi için yararlı olabilir.
Evet, tüm büyük tarayıcılar zaman aşımı kimliklerini ardışık tamsayılar olarak uygular ( spesifikasyon tarafından gerekli değildir ). Başlangıç numarası tarayıcıdan tarayıcıya farklılık gösterse de. Görünüşe göre Opera, Safari, Chrome ve IE> 8, sekme yenilemede sihirli bir şekilde kaydedilen bazı rastgele sayılardan 1'den Gecko tabanlı tarayıcılar ve IE <= 8'den zaman aşımı kimliklerini başlatıyor. Sen edebilirsiniz kendin keşfetmek .
Tüm bunlar, IE <= 8'de while (lastTimeoutId--)
döngünün 8 basamaktan fazla çalışabileceği ve " Bu sayfadaki bir komut dosyası Internet Explorer'ın yavaş çalışmasına neden oluyor " mesajını gösterebileceği anlamına gelir . Bu nedenle, tüm zaman aşımı kimliklerini kaydedemezseniz veya window.setTimeout'u geçersiz kılmak istemiyorsanız , bir sayfadaki ilk zaman aşımı kimliğini kaydetmeyi ve bu zaman aşımını temizlemeyi düşünebilirsiniz.
Kodu erken sayfa yüklemesinde yürütün:
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);
};
});
Ve sonra, muhtemelen yabancı kod tarafından birçok kez ayarlanmış olan tüm bekleyen zaman aşımlarını temizleyin
Zaman aşımı kimliklerini global bir dizide depolamaya ve işlev çağrısını pencereye devretmek için bir yöntem tanımlamaya ne dersiniz?
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
Yöntemi yeniden yazmanız ve zaman aşımı kimliğini kaydetmeniz gerekir.
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();
}
}
Aşağıdaki kodu başka herhangi bir komut dosyasının önüne yerleştirin ve orijinal setTimeout
& için bir sarmalayıcı işlevi oluşturacaktır clearTimeout
.
Nesneye, tüm (bekleyen) zaman aşımlarının ( Gist bağlantısı ) temizlenmesine izin verecek yeni bir clearTimeouts
yöntem eklenecektir .window
Diğer cevaplar , alınabilecek olası argümanlar için tam desteğe sahip değildir .
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);
Bütünlüğü sağlamak için, bunu kapakları hem genel bir çözüm sonrası istedim setTimeout
ve setInterval
.
Görünüşe göre tarayıcılar her ikisi için aynı kimlik havuzunu kullanıyor olabilir, ancak bazı yanıtlardan Are clearTimeout ve clearInterval aynı mı? , aynı işleve güvenmenin clearTimeout
ve bunu clearInterval
gerçekleştirmenin mi yoksa yalnızca ilgili zamanlayıcı türlerinde çalışmanın güvenli olup olmadığı açık değildir .
Bu nedenle, amaç tüm zaman aşımlarını ve aralıkları sonlandırmak olduğunda, işte hepsini test edemediğinde uygulamalar arasında biraz daha savunmacı olabilecek bir uygulama:
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(){}
}
Mevcut penceredeki tüm zamanlayıcıları temizlemek için kullanabilirsiniz:
clearAll(window);
Ya da aşağıdaki tüm zamanlayıcıları temizlemek için kullanabilirsiniz iframe
:
clearAll(document.querySelector("iframe").contentWindow);
Typecript ile Vue kullanıyorum.
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
}
}
Bu çok geç ... ama:
Temel olarak, setTimeout / setInterval ID'leri ardışık sırada gider, bu yüzden en yüksek ID'yi elde etmek için sadece bir kukla zaman aşımı işlevi oluşturun, ardından bundan daha düşük tüm ID'lerde aralığı temizleyin.
const highestId = window.setTimeout(() => {
for (let i = highestId; i >= 0; i--) {
window.clearInterval(i);
}
}, 0);
Diğer tüm işlevlerinizin zamanlamayı elde ettiği global bir zaman aşımı kullanın. Bu, kodunuza biraz soyutlama katacak olsa da, her şeyin daha hızlı çalışmasını sağlayacak ve yönetilmesi daha kolay olacaktır.
set_timeout
Global işlevin davranışını genişletmek mi istiyorsunuz? Örnek bir kod verebilir misiniz?
Tam olarak bu sorunu çözen bir paket yayınladık.
npm install time-events-manager
Bununla, tüm zaman aşımlarını ve aralıkları timeoutCollection
& intervalCollection
nesneler aracılığıyla görüntüleyebilirsiniz . Ayrıca removeAll
hem koleksiyondaki hem de tarayıcıdaki tüm zaman aşımlarını / aralıkları temizleyen bir işlev vardır.