有没有办法清除给定窗口中的所有超时?我想超时存储在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());
}
}
要清除所有超时,必须先"捕获"它们:
将以下代码放在任何其他脚本之前,它将为原始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(){
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)
看到一段很好的代码,我称之为"更好的超时",它比上面做得更多。
为了完整起见,我想发布一个涵盖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
}
}
使用全局超时,所有其他函数都从中派生计时。 这将使一切运行得更快,并且更易于管理,尽管它会为您的代码添加一些抽象。
我们刚刚发布了一个解决这个确切问题的软件包。
npm install time-events-manager
有了它,您可以通过timeoutCollection
和intervalCollection
对象查看所有超时和间隔。还有一个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);
}