javascript:清除所有超时?

mar*_*cio 86 javascript timeout

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

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

use*_*621 116

它们不在window对象中,但它们有id,其中(afaik)是连续的整数.

所以你可以清除所有超时:

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

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

  • 它不需要从1开始.[HTML5](http://www.w3.org/TR/html5/timers.html#timers)规范说"让我们处理一个大于零的用户代理定义的整数这将识别此呼叫设置的超时." 这使句柄的空间成为任何正整数,包括非连续和非小整数. (5认同)
  • 这是规范的一部分,还是依赖于实现? (3认同)
  • 这非常聪明,但OP可能会问是否有更好的解决方案可以跟踪活动计时器. (3认同)
  • 由于我询问了如何清除所有超时,因此我接受了这个答案。非常聪明的解决方案。 (3认同)
  • 这不是一个无限循环吗?并非所有浏览器都将if(0)呈现为false。 (2认同)

Mic*_*ski 73

我认为实现这一目标的最简单方法是将所有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]);
}
Run Code Online (Sandbox Code Playgroud)

  • 这有额外的(或我可能的缺点)只清除你设置的那些,所以你不会无意中破坏外部代码. (13认同)
  • 也许我想在我进入一个我无法控制的网页时清除所有超时和间隔,因为他们有一个恼人的弹出式广告,直到我的广告拦截器运行后才开始播放. (4认同)
  • 我现在感到平静:) (3认同)
  • +1,不会清除所有超时,但是一次清除特定组超时的好方法 (2认同)
  • @marcioAlmada奇怪,但很酷,看到你再回来评论2.5yrs后:) (2认同)

小智 11

我对Pumbaa80的答案有所补充,这可能对开发旧IE的人有用.

是的,所有主流浏览器都将超时ID实现为连续整数(规范不要求).通过起始编号从浏览器到浏览器不同.似乎Opera,Safari,Chrome和IE> 8从1启动超时ID,从2启动基于Gecko的浏览器,从一些随机数启动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);
    };
});
Run Code Online (Sandbox Code Playgroud)

然后清除所有可能由外部代码设置的挂起超时,这是您想要的多次


Jas*_*key 9

如何将超时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
    }
};
Run Code Online (Sandbox Code Playgroud)


vsy*_*ync 7

要清除所有超时,必须首先“捕获”它们:

将以下代码放在任何其他脚本之前,它将为原始setTimeout&创建一个包装函数clearTimeout

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)
Run Code Online (Sandbox Code Playgroud)

请参阅一段不错的代码,我将其命名为“better-timeout”,它的作用比上面的要多一些。


gue*_*est 5

您必须重写该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();
  }
}
Run Code Online (Sandbox Code Playgroud)


cha*_*rri 5

这已经很晚了……但是:

基本上,setTimeout/setInterval ID 的顺序是连续的,因此只需创建一个虚拟超时函数来获取最高 ID,然后清除所有低于该 ID 的 ID 的间隔。

const highestId = window.setTimeout(() => {
  for (let i = highestId; i >= 0; i--) {
    window.clearInterval(i);
  }
}, 0);
Run Code Online (Sandbox Code Playgroud)

  • 不错的解决方案,但请注意,与其他一些答案不同,这不会立即清除超时;它将等待直到下一个事件循环。 (3认同)