javascript:清除所有超时?
Posted
技术标签:
【中文标题】javascript:清除所有超时?【英文标题】:javascript: Clear all timeouts? 【发布时间】:2012-02-10 05:22:47 【问题描述】:有没有办法清除给定窗口的所有超时?我想超时存储在 window
对象中的某处,但无法确认。
欢迎任何跨浏览器解决方案。
【问题讨论】:
How to stop all timeouts and intervals using javascript? 的可能重复项 老兄,这个问题是 3 年前的问题,里面有很好的答案。没必要搞砸。 我搜索了这个并找到了两者。你的问题比较大,所以我认为将这两个问题减少到一个是很好的家务。我的只有一票;更多的人需要投票才能关闭,重复的链接可能会帮助其他人。 @Bernard Hofmann 我不确定如果这个问题得到了更好的答案,它是否算作重复问题。从 2010 年开始,人们接受的答案是“否”。 在任何合理大小的系统中执行此操作都是个坏主意。你可以在系统中完全不相关的部分杀死你不知道的任务。 【参考方案1】:它们不在窗口对象中,但它们有 ids,它们 (afaik) 是连续的整数。
所以你可以像这样清除所有超时:
var id = window.setTimeout(function() , 0);
while (id--)
window.clearTimeout(id); // will do nothing if no timeout with id is present
【讨论】:
这是规范的一部分,还是依赖于实现? 它不需要从 1 开始。html5 规范说“让句柄是一个大于零的用户代理定义的整数,它将标识此调用设置的超时。”这为句柄留出了空间,可以是任何正整数,包括非连续和非小整数。 这很聪明,但 OP 应该会问是否有更好的解决方案来跟踪活动计时器。 这不是无限循环吗?并非所有浏览器都将 if(0) 呈现为 false。 既然我问过如何清除所有超时,我接受了这个答案。非常聪明的解决方案。【参考方案2】:我认为完成此操作的最简单方法是将所有 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]);
【讨论】:
这有好处(或潜在的缺点,我猜)只清除 你 设置的那些,所以你不会无意中破坏外部代码。 +1,不会清除所有超时,但是是一次清除特定组超时的好方法 这是最好的解决方案,因为它不会破坏外部代码,但由于我问过如何清除所有超时,我最终接受了@Pumbaa80 答案:) @marcioAlmada 很奇怪,但很高兴看到你在 2.5 年后再次对此发表评论:) 也许我想在进入我无法控制的网页时清除所有超时和间隔,因为它们有一个烦人的弹出广告,直到我的广告拦截器运行后才会开始。跨度> 【参考方案3】:我对@987654321@ 有一个补充,它可能对为旧 IE 开发的人有用。
是的,所有主流浏览器都将超时 id 实现为连续整数(即not required by specification)。尽管起始编号因浏览器而异。似乎 Opera、Safari、Chrome 和 IE > 8 从 1 开始超时 ID,基于 Gecko 的浏览器从 2 开始,IE discover it yourself。
这意味着在 IE while (lastTimeoutId--) 循环可能会运行超过 8 位,并显示“此页面上的脚本导致 Internet Explorer 运行缓慢”消息。因此,如果您不能save all you timeout id's 或不想override 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);
;
);
然后清除所有可能由外部代码设置的所有未决超时
【讨论】:
加一个用于澄清一些更详细的信息。【参考方案4】:这已经很晚了……但是:
基本上,setTimeout/setInterval ID 的顺序是连续的,所以只需创建一个虚拟超时函数来获取最高 ID,然后清除所有低于该 ID 的间隔。
const highestId = window.setTimeout(() =>
for (let i = highestId; i >= 0; i--)
window.clearInterval(i);
, 0);
【讨论】:
这对我来说是最好的解决方案!!谢谢你,查里 在 for 循环内,clearInterval 还是 clearTimeout? 任何一个都有效,因为它们基本上做同样的事情 不错的解决方案,但请注意,与其他一些答案不同,这不会立即清除超时;它将等到下一个事件循环。 太棒了!这正是我一直在寻找的。 +1【参考方案5】:如何将超时 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
;
【讨论】:
【参考方案6】:你必须重写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();
【讨论】:
【参考方案7】:要清除所有超时,必须先“捕获”它们:
将以下代码放在任何其他脚本之前,它将为原始setTimeout
和clearTimeout
创建一个包装函数。
一个新的clearTimeouts
方法将添加到window
对象,这将允许清除所有(待定)超时(Gist link)。
其他答案缺乏完整支持
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);
【讨论】:
这是最正确最完整的答案。【参考方案8】:为了完整起见,我想发布一个涵盖setTimeout
和setInterval
的通用解决方案。
似乎浏览器可能对两者使用相同的 ID 池,但从对 Are clearTimeout and clearInterval the same? 的一些答案来看,尚不清楚依赖 clearTimeout
和 clearInterval
执行相同功能或仅工作是否安全关于它们各自的计时器类型。
因此,当目标是终止所有超时和间隔时,这里的实现可能会在无法测试所有实现时稍微更具防御性:
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-cli-service 观察程序,因此您在清除所有超时和时间间隔时无法进行热重载。我认为对于其他框架的热重载观察者来说也是一样的,比如(angular、react、ember 等)【参考方案9】:我使用 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
【讨论】:
【参考方案10】:使用全局超时,您的所有其他函数都从中派生计时。这将使一切运行得更快,更易于管理,尽管它会为您的代码添加一些抽象。
【讨论】:
我不完全理解你。您的意思是扩展set_timeout
全局函数的行为?能给个示例代码吗?
我的意思是你有一个全局超时,每 50 毫秒运行一次。然后,需要计时元素的所有其他功能将从全局超时中获取它。谷歌为了提高效率而改用这个,虽然我再也找不到引用它的文章了。【参考方案11】:
我们刚刚发布了一个解决这个确切问题的包。
npm install time-events-manager
这样,您可以通过timeoutCollection
和intervalCollection
对象查看所有超时和间隔。
还有一个removeAll
函数可以清除集合和浏览器中的所有超时/间隔。
【讨论】:
【参考方案12】:函数f(...)和timeout定义后的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());
【讨论】:
以上是关于javascript:清除所有超时?的主要内容,如果未能解决你的问题,请参考以下文章