如何使用javascript停止所有超时和间隔?

时间:2010-06-29 13:29:04

标签: javascript

我正在开发一个包含许多运行超时和间隔的ajax Web应用程序。现在我需要清除所有正在运行的超时和间隔。是否有一种简单的方法来阻止所有内容而无需存储每个超时和间隔ID并迭代它们并清除它们?

10 个答案:

答案 0 :(得分:73)

有时可以保存计时器ID / Handle以便稍后清除它,这将是最佳解决方案。所以这是第二好的。但我想更好地了解正在发生的事情。它基本上抓住了最高的计时器ID并清除了所有内容。 但是也可以清除其他你不想清除的计时器!

有点hackish,所以请注意!

// Set a fake timeout to get the highest timeout id
var highestTimeoutId = setTimeout(";");
for (var i = 0 ; i < highestTimeoutId ; i++) {
    clearTimeout(i); 
}

答案 1 :(得分:25)

阅读完副本后更新了答案我用 -

结束了这个问题

它在OSX上的Chrome中运行和测试

// run something
var id1 = setInterval(function() { console.log("interval", new Date())}, 1000);
var id2 = setTimeout(function()  { console.log("timeout 1", new Date())}, 2000);
var id3 = setTimeout(function()  { console.log("timeout 2", new Date())}, 5000); // not run
          setTimeout(function()  { console.log("timeout 3", new Date())}, 6000); // not run

// this will kill all intervals and timeouts too in 3 seconds. 
// Change 3000 to anything larger than 10

var killId = setTimeout(function() {
  for (var i = killId; i > 0; i--) clearInterval(i)
}, 3000);

console.log(id1, id2, id3, killId); // the IDs set by the function I used

注意:查看具有数字类型的窗口对象 - 有趣的是,IE分配了一个8位数字,FF是一个以2开头的单个数字

答案 2 :(得分:16)

这是一种解决方法。

window.timeoutList = new Array();
window.intervalList = new Array();

window.oldSetTimeout = window.setTimeout;
window.oldSetInterval = window.setInterval;
window.oldClearTimeout = window.clearTimeout;
window.oldClearInterval = window.clearInterval;

window.setTimeout = function(code, delay) {
    var retval = window.oldSetTimeout(code, delay);
    window.timeoutList.push(retval);
    return retval;
};
window.clearTimeout = function(id) {
    var ind = window.timeoutList.indexOf(id);
    if(ind >= 0) {
        window.timeoutList.splice(ind, 1);
    }
    var retval = window.oldClearTimeout(id);
    return retval;
};
window.setInterval = function(code, delay) {
    var retval = window.oldSetInterval(code, delay);
    window.intervalList.push(retval);
    return retval;
};
window.clearInterval = function(id) {
    var ind = window.intervalList.indexOf(id);
    if(ind >= 0) {
        window.intervalList.splice(ind, 1);
    }
    var retval = window.oldClearInterval(id);
    return retval;
};
window.clearAllTimeouts = function() {
    for(var i in window.timeoutList) {
        window.oldClearTimeout(window.timeoutList[i]);
    }
    window.timeoutList = new Array();
};
window.clearAllIntervals = function() {
    for(var i in window.intervalList) {
        window.oldClearInterval(window.intervalList[i]);
    }
    window.intervalList = new Array();
};

适用于执行这些行后调用的set / clear超时/间隔函数。试着看看它是否有效:

setInterval('console.log(\'a\')', 1000);
setInterval('console.log(\'b\')', 500);
setInterval('console.log(\'c\')', 750);
setTimeout('clearAllIntervals()', 10000);

代理是神奇的。

答案 3 :(得分:12)

var noofTimeOuts = setTimeout('');
for (var i = 0 ; i < noofTimeOuts ; i++) clearTimeout(i);

答案 4 :(得分:7)

var max = setTimeout(function(){ /* Empty function */ },1);

        for (var i = 1; i <= max ; i++) {
            window.clearInterval(i);
            window.clearTimeout(i);
            if(window.mozCancelAnimationFrame)window.mozCancelAnimationFrame(i); // Firefox
        }

答案 5 :(得分:3)

没有任何内置内容,但通过调用此clearAll()函数来展示所有当前未完成的延迟执行函数非常容易:

function clearAll() {
  for (var i = setTimeout(function() {}, 0); i > 0; i--) {
    window.clearInterval(i);
    window.clearTimeout(i);
    if (window.cancelAnimationFrame) window.cancelAnimationFrame(i);
  }
}

如果你负责你运行的页面,并且可以将本机延迟执行函数包装在用于保存的包装器中,当然也要为每个setter函数配备相应的.clearAll()

(function(deferFunctions) {
  for (var setter in deferFunctions) (function(setter, clearer) {
    var ids = [];
    var startFn = window[setter];
    var clearFn = window[clearer];

    function clear(id) {
      var index = ids.indexOf(id);
      if (index !== -1) ids.splice(index, 1);
      return clearFn.apply(window, arguments);
    }
    function set() {
      var id = startFn.apply(window, arguments);
      ids.push(id);
      return id;
    }
    set.clearAll = function() { ids.slice(0).forEach(clear); };

    if (startFn && clearFn) {
      window[setter] = set;
      window[clearer] = clear;
    }
  })(setter, deferFunctions[setter]);
})(
{ setTimeout: 'clearTimeout'
, setInterval: 'clearInterval'
, requestAnimationFrame: 'cancelAnimationFrame'
});

为了尝试它的工作原理,你可以尝试这样做,例如,它将保持沉默,因为没有一个回调在他们再次被取消之前结束:

// Some example timers of all types:
requestAnimationFrame(console.error);
setInterval(console.info, 1000, 'interval');
setTimeout(alert, 0, 'timeout');

// Now you can clear all deferred functions
// by execution type, whenever you want to:
window.setTimeout.clearAll();
window.setInterval.clearAll();
window.requestAnimationFrame.clearAll();

答案 6 :(得分:1)

将一个小黑客添加到Gokhan Ozturk's answer

如果您使用的是使用TimeoutsIntervals的第三方库,那么它们也会被清除,因此我添加了一个参数来通知函数此间隔为push'编辑或不编辑。

window.setTimeout = function(code, delay, toBeAdded) {
    var retval = window.oldSetTimeout(code, delay);
    var toBeAdded = toBeAdded || false;
    if(toBeAdded) {
        window.timeoutList.push(retval);
    }
    return retval;
};
... // likewise for all functions.

答案 7 :(得分:1)

您最好创建一个调度程序。看看Nader Zeid的这种方法:

https://www.onsip.com/blog/avoiding-javascript-settimeout-and-setinterval-problems

这是一种有助于创建一些确定性的方法(因为&#34;每个函数的时间间隔参数实际上只确定给定函数将在至少这段时间后执行。所以定时事件可以在任何时间内错过目标。&#34;)。

具体来说,对于您在这里提出的问题,您可以轻松地在队列中添加和删除功能。虽然这个问题在问题提出后很长时间,但希望它对那些发现自己在Timeout和Intervals中挣扎的人有所帮助。

答案 8 :(得分:0)

您无法清除任何您不知道的超时和间隔。

你需要getTimeoutList之类的东西,这些东西不在DOM3规范中,甚至不是计划中的AFAIK。

答案 9 :(得分:-2)

之前的代理技巧很不错,但是如果你有很多超时和间隔,我不会用连续的数字[1,2,3....]填充数组,但是会有间隔。例如,您可以使用[1,2,3,7,8,9]['1-3','7-9']作为内存优化,而不是使用[[1,3],[7,9]]。当然,这个技巧只适用于你有很多超时和间隔时间,以及你不会经常停止任意间隔的情况。