首先,我們強烈建議您提供一個回調(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
爲倍(幾乎)無限的數字,但它永遠不會完成它。
在這種情況下的解決方案是仿效setInterval
與setTimeout
,以保證再次調用它之前的回調完成執行:現在
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);
}
如果你有興趣,我已經重寫了setInterval
和clearInterval
功能,以便在任何地方使用它們,沒有照顧堆棧溢出的:
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;
}
請使用'的setInterval(b,1000);而不是 - 不要使用字符串。 – pimvdb
如果文檔中使用異步「線程」(例如AJAX)的JavaScript代碼更多,它可能會延遲。 –
閱讀此:http://ejohn.org/blog/how-javascript-timers-work/ – c69