2016-02-04 87 views
1

我是一個第三方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 - 正確。 –

回答

0

這將是有趣的,知道爲什麼他們運行醜陋的代碼...

無論如何,你的想法寫東西醜陋是朝着正確方向邁出的一步,但你可以推醜陋的一個檔次,沒有觸及他們自己的功能(你是第三方,請記住 - 我很驚訝你甚至有權看他們的代碼)。你甚至不會有額外的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

0

所以有辦法:把你的setTimeout調用到像WebWorkerIFrame一個與世隔絕的地方,然後提供一些事件監聽。

我知道這只是一個setTimeout的黑客攻擊,但是更好的方法是更換clearInterval。

0

我能想到的唯一方法就是玩髒太 - 重新定義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