2011-09-21 48 views
2

99超時100,這完美地工作:setInterval(javaScript):有沒有已知的錯誤?

function a(){ 
    setInterval("b()",1000); 
    updateText("still working"); 
} 
function b(){ 
    timer++; 
    updateText(timer); 
} 

偶爾第一環路等待20秒至2分鐘。此後它運行完美。我知道計時器可以在Android手機上暫停(當顯示軟鍵盤時)。是否有其他可能延遲setInterval的條件?

+4

請使用'的setInterval(b,1000);而不是 - 不要使用字符串。 – pimvdb

+0

如果文檔中使用異步「線程」(例如AJAX)的JavaScript代碼更多,它可能會延遲。 –

+0

閱讀此:http://ejohn.org/blog/how-javascript-timers-work/ – c69

回答

1

試試這個,

setInterval(b, 1000); 

setInterval(function(){ 
    timer++; 
    updateText(timer); 
}, 1000); 
+0

謝謝。我已經遵循了你的第一個建議,因爲我的實際功能比我展示的例子要大得多。 –

9

首先,我們強烈建議您提供一個回調(function)作爲第一個參數,而不是一個字符串,因爲該字符串的評估全球範圍內,我們都知道,當我們在js中使用eval時,會發生不好的事情(相關eval post:When is JavaScript's eval() not evil?)。
所以,你

setInterval("b()", 1000); 

應該寫成:

setInterval(b, 1000); 

或:

setInterval(function() { b(); }, 1000); 

我也建議你使用setTimeout模擬setInterval

setInterval函數的主要缺點是它每執行一個代碼塊就會執行一個代碼塊,而不管前面的代碼塊是否執行。
所以如果由於某種原因setInterval回調需要比提供的延遲執行更長的時間,它將導致一些stack overflows

讓我們以下面的代碼,例如:

function foo() { 
    // this takes about 2 seconds to execute 
    // .. code here 
} 
setInterval(foo, 1000); 

這實際上將凍結瀏覽器,因爲它會執行foo爲倍(幾乎)無限的數字,但它永遠不會完成它。

在這種情況下的解決方案是仿效setIntervalsetTimeout,以保證再次調用它之前的回調完成執行:現在

function foo() { 
    // this takes about 2 seconds to execute 
    // .. code here 
} 
function newSetInterval(callback, duration, callbackArguments) { 
    callback.apply(this, callbackArguments); 
    var args = arguments, 
     scope = this; 

    setTimeout(function() { 
     newSetInterval.apply(scope, args); 
    }, duration); 
} 
newSetInterval(foo, 1000); 

foo又被稱爲後,才前一個實例已完成代碼執行。

我將適用同樣的事情在你的代碼,爲了讓瀏覽器決定時,它可以執行的代碼,而不是強制執行代碼天氣的塊是忙碌的那一刻與否:

function a() { 
    newSetInterval(b, 1000); 
    updateText("still working"); 
} 
function b() { 
    timer++; 
    updateText(timer); 
} 
function newSetInterval(callback, duration, callbackArguments) { 
    callback.apply(this, callbackArguments); 
    var args = arguments, 
     scope=this; 

    setTimeout(function() { 
     newSetInterval.apply(scope, args); 
    }, duration); 
} 

如果你有興趣,我已經重寫了setIntervalclearInterval功能,以便在任何地方使用它們,沒有照顧堆棧溢出的:

function setInterval(f, time) { 
    setInterval.ids = setInterval.ids || {}; 
    setInterval.idCount = setInterval.idCount || 0; 
    var that = this, 
     id = setInterval.idCount++, 
     // to prevent firefox bug that adds an extra element to the arguments 
     l = arguments.length - 2; 

    (function theFn() { 
     // to prevent firefox bug that adds an extra element to the arguments 
     var args = [].slice.call(arguments, 0, l); 
     f.apply(this, args); 
     setInterval.ids[id] = setTimeout.apply(this, [theFn, time].concat(args)); 
    }).apply(that, [].slice.call(arguments, 2, arguments.length)); 
    return id; 
} 


function clearInterval(id) { 
    if(!setInterval.ids || !setInterval.ids[id]) { 
     return false; 
    } 
    clearTimeout(setInterval.ids[id]); 
    return true; 
} 
+2

明智地使用此網站名稱+1和正確的信息。 :) –

+0

這非常有趣。我正在製作基於瀏覽器的遊戲,所以在開始時就有很多代碼。我會按照你的建議。謝謝! –

+0

在你呈現'setTimeout(bar,duration,callbackArguments)的代碼的多個代碼片段中;'我得到錯誤,提示'bar'沒有定義,當然你的意思是把'callback'放在那個地方而不是'bar'? – user17753

相關問題