2011-09-21 78 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

相关问题