清除所有超时?

有没有办法清除给定窗口的所有超时?我认为超时存储在 window对象的某个地方,但是无法确认。

欢迎任何跨浏览器的解决方案。

110082 次浏览

它们不在窗口对象中,但是它们具有 id,id (afaik)是连续的整数。

因此,您可以像下面这样清除所有超时:

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


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

我认为实现这一点的最简单方法是将所有 setTimeout标识符存储在一个数组中,您可以轻松地在所有数组上迭代到 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的回答,可能是有用的人开发旧的工程师。

是的,所有主流浏览器都将超时 id 实现为连续的整数(即 不是规格要求的)。虽然起始号码各浏览器不同。Opera,Safari,Chrome 和 IE > 8从1开始启动超时 id,基于 Gecko 的浏览器从2开始启动,IE < = 8从一些随机数开始,这些随机数神奇地通过标签刷新保存。你可以 自己去发现

所有这些意味着在 IE < = 8中,while (lastTimeoutId--)循环可以运行超过8位数的次数并显示“ 这个页面上的脚本导致 Internet Explorer 运行缓慢”消息。因此,如果您不能 保存你所有的暂停 ID或不想 重写 window.setTimeout,您可以考虑保存页面上的第一个超时标识,并清除超时直到它。

在早期页面加载时执行代码:

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

我们刚刚发布了一个解决这个问题的方案。

npm install time-events-manager

这样,您就可以通过 timeoutCollectionintervalCollection对象查看所有的超时和间隔。 还有一个 removeAll函数,它可以清除集合和浏览器中的所有超时/间隔。

为了清除所有的 暂停,他们必须“捕获”第一:

放置下面的代码 在任何其他剧本之前,它将为原来的 setTimeoutclearTimeout创建一个包装函式。

新的 clearTimeouts方法将被添加到 window对象,这将允许清除 所有(挂起)超时(主要链接)。

其他答案缺乏 完整支持的可能 争论 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(){
removeCacheItem(id)
CB.apply(null, arguments)
}, 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);


// lets define some timeouts


setTimeout(()=> console.log('1s passed'), 1000); // should run
setTimeout(()=> console.log('2s passed'), 2000); // should be cleared
setTimeout(()=> console.log('3s passed'), 3000); // should be cleared




// lets clear them all after 1 and a half second:
setTimeout(()=> {
window.clearTimeouts()
}, 1500)

看到一个不错的代码片段,我命名为 “更好的暂停”,其中做了一点比上面。

为了完整起见,我想发布一个涵盖 setTimeoutsetInterval的通用解决方案。

看起来浏览器可能对两者使用相同的 ID 池,但是从 ClearTimeout 和 clearInterval 是否相同?的一些答案来看,依赖于 clearTimeoutclearInterval执行相同的功能是否安全,或者只在它们各自的定时器类型上工作,还不清楚。

因此,当目标是消除所有的超时和间隔时,这里有一个实现,当无法测试所有的超时和间隔时,它在实现之间可能稍微更具防御性:

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

我使用 Vue 和 Type 脚本。

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

您必须重写 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/setInterval ID 是按照连续顺序排列的,所以只需创建一个虚拟超时函数来获得最高的 ID,然后在所有低于这个值的 ID 上清除间隔。

const highestId = window.setTimeout(() => {
for (let i = highestId; i >= 0; i--) {
window.clearInterval(i);
}
}, 0);

SetTimeout内定义 函数 f (...){}暂停后可以添加参数。

例如: $setTimeout (函数(A B){ run (a) ; run (b) ; } ,100,A B) ;)

... args 解决了这个问题。

    var $timeouts = new Array();


function $setTimeout(...args)
{
var t = window.setTimeout(...args);
$timeouts.push(t);
return t;
}


function $clearTimeout(id)
{
if( $timeouts.indexOf(id) > -1 )
$timeouts = $timeouts.filter(n => n != id )


window.clearTimeout(id);
}




function $clearTimeouts()
{
while($timeouts.length)
window.clearTimeout($timeouts.pop());
}

对于老式浏览器,您需要使用其他方法来传递参数并从数组 $timeouts 中删除一个值。

var $timeouts = new Array();


function $setTimeout()
{
var t = window.setTimeout.apply( this, arguments );
$timeouts.push(t);
return t;
}


function $clearTimeout(id)
{
var index = $timeouts.indexOf(id);


if (index > -1) {
$timeouts.splice(index, 1);
}


window.clearTimeout(id);
}




function $clearTimeouts()
{
while($timeouts.length)
window.clearTimeout($timeouts.pop());
}

其他人的答案实际上是正确的。但对我来说,这就是如何接近这种东西。检查下我的密码。


// example when I person types on search input
function typeOnSearch(time = 3000) {
// this will clear timeout
clearTimeout(window.typeOnSearchTimeOut);


// we create a timeout variable and added it to window, this way, we can access this in any function in our app.
window.typeOnSearchTimeOut = setTimeout( () => {
//enter what you like to do here, like fetch data
}, time);
}