如何防止clearInterval断裂的setTimeout

问题描述:

我是一个第三方JavaScript开发和我的一个客户都有自己的网页,在下列代码被反复运行:如何防止clearInterval断裂的setTimeout

for (var i = 1; i < 99999; i++) { 
    window.clearInterval(i); 
} 

当然,这打破了我的setInterval环。我想我会解决这个问题,只需使用setTimeout,如果还没有满足一些条件,则会创建另一个setTimeout。令我惊讶的是,clearInterval以上的代码打破我的超时。

您可以观察这种行为,甚至没有建立一个setTimeout循环,但只是一个孤立的定时器(我把它包在一些额外的代码,以保持它关闭窗口):

var example = (function(){ 
    return { 
    foo: setTimeout(function(){ 
     console.log('bar'); 
    }, 5000) 
    }; 
}()); 

for (var i = 1; i < 99999; i++) { 
    window.clearInterval(i); 
} 

我能想到的唯一的事情如果覆盖内置的clearInterval来清除我的计时器,但是这对我来说似乎非常非常错误和肮脏。

var originalClearInterval = window.clearInterval; 

var exampleLoop = setInterval(function() { 
    console.log('loop running'); 
    if(typeof window.stopRunning !== 'undefined' && window.stopRunning === true) { 
    window.clearInterval = originalClearInterval; 
    clearInterval(exampleLoop); 
    console.log('loop finished'); 
    } 
}, 50); 

window.clearInterval = function(timerId) { 
    if(timerId !== exampleLoop) { 
    originalClearInterval.apply(this, arguments); 
    } 
} 
+3

这基本上是/ API/WindowTimers/clearInterval)完全错误的方式 – Rhumborl

+0

将你的间隔设置为一个变量,所以你可以'clearInterval(intervalID)'而不是清除所有的东西。 –

+0

@Rhumborl - 正确。 –

这将是有趣的,知道为什么他们运行丑陋的代码...

无论如何,你的想法写东西丑陋是朝着正确方向迈出的一步,但你可以推丑陋的一个档次,没有触及他们自己的功能(你是第三方,请记住 - 我很惊讶你甚至有权看他们的代码)。你甚至不会有额外的ID管理的事情:因为他们使用的是[`clearInterval()`](https://developer.mozilla.org/en-US/docs/Web

function setBulletproofTimeout(code, delay) { 

    var minId = 99999; 
    var id = 0; 
    var myIntervals = []; 
    for (var i = 0; i<=minId; i++) { 
     id = window.setTimeout(code, delay); 
     if(id >= minId) { 
      // that's the One, kill the others 
      myIntervals.forEach(function(e) { window.clearInterval(e); }); 
      return id; 
     } 
     else { 
      myIntervals.push(id); 
     } 
    } 
} 
+0

哈哈,辉煌! –

+0

一般来说,我喜欢这个答案,但我认为'return id;'会更好,而不是'break';这样我们仍然可以正确清除计时器(并且符合setTimeout/setInterval api)。我对这种方法的一个担忧是它可能会通过让他们的代码创建他们需要清除的范围之外的定时器来破坏_their_代码(因为所有较低的id已经被使用了) –

+0

@BeauLynn-Miller你是对的,我会改变它。关于你的担忧,我真的认为(开玩笑说)处理这种情况的正确方法是理解他们为什么这样做并采取相应行动。否则,你处于一种“未定义的行为”区域,你不能确定做正确的事情。 – Ilya

所以有办法:把你的setTimeout调用到像WebWorkerIFrame一个与世隔绝的地方,然后提供一些事件监听。

我知道这只是一个setTimeout的黑客攻击,但是更好的方法是更换clearInterval。

我能想到的唯一方法就是玩脏太 - 重新定义window.clearInterval,不理会清除你的超时IDS:

// create an array to store timeout IDs to ignore. 
 
window.ignoreTimeoutIds = []; 
 

 
// store original clearInterval function as another property 
 
window.clearInterval2 = window.clearInterval; 
 

 
// redefine clearInterval to not clear if it is one of your timeoutIds 
 
window.clearInterval = function(intervalId) { 
 
    if (window.ignoreTimeoutIds.indexOf(intervalId) > -1) 
 
    console.log('not clearing 1'); // for demo purposes 
 
    else 
 
    window.clearInterval2(intervalId); 
 
}; 
 

 

 
(function() { 
 

 
    //set the timeout and get its ID 
 
    var timeoutId = setTimeout(function() { 
 
    console.log('bar'); 
 
    // don't forget to remove the timeoutId from the ignore list 
 
    window.ignoreTimeoutIds.splice(window.ignoreTimeoutIds.indexOf(timeoutId)) 
 
    }, 5000); 
 

 
    // add the timeoutID to the ignore list 
 
    window.ignoreTimeoutIds.push(timeoutId); 
 
}()); 
 

 
for (var i = 1; i < 99999; i++) { 
 
    window.clearInterval(i); 
 
}

您还可以创建一个包装为setTimeout()以处理添加和从阵列中删除,如果你想该部分是整洁。

+0

确定没有看到您的编辑...是的,这是错误的和肮脏的,但他们没有为“良好的编码”设置良好的基线 – Rhumborl