javascript:清除所有超时



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

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

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

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

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

这已经很晚了...但:

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

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

我对Pumbaa80的答案有一个补充,可能对为旧IE开发的人有用。

是的,所有主流浏览器都将超时 ID 实现为连续整数(规范不需要(。虽然起始号码因浏览器而异。似乎Opera,Safari,Chrome和IE> 8从1开始超时ID,基于壁虎的浏览器从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());
  }
}

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

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

💡 新的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(){
          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与Typescript一起使用。

    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

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

在函数 f(...( 定义后的 setTimeout 内部{}超时可以是附加参数。

例如: $setTimeout( function(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);
}

相关内容

  • 没有找到相关文章