有没有办法清除给定窗口中的所有超时?我想超时存储在window
对象中的但无法确认。
任何跨浏览器解决方案都是受欢迎的。
有没有办法清除给定窗口中的所有超时?我想超时存储在window
对象中的但无法确认。
任何跨浏览器解决方案都是受欢迎的。
Answers:
它们不在window对象中,但是具有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的答案,我还有一个补充,它可能对为旧IE开发的人有用。
是的,所有主要的浏览器都将超时ID实现为连续的整数(规范不需要)。整个浏览器之间的起始编号不同。似乎Opera,Safari,Chrome和IE> 8从1开始,基于Gecko的浏览器的超时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();
}
}
将以下代码放在任何其他脚本之前,它将为原始setTimeout
&创建包装函数clearTimeout
。
新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(){
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);
为了完整起见,我想发布一个涵盖setTimeout
和的通用解决方案setInterval
。
似乎浏览器可能对这两者使用相同的ID池,但是从对clearTimeout和clearInterval是否相同的一些答案中得出?,尚不清楚依靠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与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
}
}
使用全局超时,您的所有其他函数都将从中导出超时。尽管它将为您的代码添加一些抽象,但这将使所有内容运行起来更快,并且更易于管理。
set_timeout
全局功能的行为?你能举个例子代码吗?