Firefox太快调用setTimeout函数(或Date.getTime()关闭?)

时间:2012-06-04 01:24:45

标签: javascript jquery

我在Firefox 12中遇到了一个奇怪的问题.setTimeout()似乎并不总是等待适当的长度。或者也许是没有jive的日期毫秒?

Check out this fiddle.基本上,100ms的setTimeout似乎在80ms到110ms之间的任何地方运行。基于John Resig's explanation of timers,我可以理解更多内容。但是少了?

您可能需要刷新一次或两次以查看问题,因为它有时在第一次运行时正常工作。它似乎在IE和Chrome中起到了很大的作用。

这是我在小提琴中使用的代码:

var txt = '',
    TIMEOUT_LENGTH = 100,
    _now;

now = Date.now || function() { return new Date().getTime() };

function log(time) {
    c = time < 100? 'class="error"' : '';
    $('#log').append('<p '+c+'>waited ' + time + '</p>');
}

function defer() {
    var d = $.Deferred(),
        start = now();
    setTimeout(function() {
        d.resolve(now() - start);
    }, TIMEOUT_LENGTH);
    return d.promise();
}

for (var i = 0; i < 20; i++) {
    defer().then(log);
}

以下是古怪输出的示例:

enter image description here

这是我的浏览器信息:

enter image description here

非常感谢您阅读我的问题!我希望有人可以对此有所了解。

更多信息

我通过使用setInterval()并检查每个增量以查看是否已经过了所需的时间来解决这个问题。 See this fiddle

然而,我仍然非常有兴趣听听是否有人能够解决问题的根源

3 个答案:

答案 0 :(得分:3)

是。 setTimeout的准确性取决于许多因素,并不保证始终在您指定的确切时间执行。

我不能用任何权威来说这个,但我猜测Firefox会试图看起来更快,会暂时加速JS引擎以使一切运转起来(这很有趣,因为根据我的经验,基于计时器的函数实际上最初在我的firefox版本中运行较慢。)

setTimeoutsetInterval都不会保证它们会在恰当的时间执行,就像您发布的链接所述。然而,使用setInterval,您可以获得定时器循环的好处,如果它落后太远就可以通过追赶来“纠正自己”,所以对于您要做的任何事情,它可能更多合适的。

无论如何,这是我在Macbook 10.6.8上的结果:

Firefox 5.0.1:

waited 92
waited 92
waited 93
waited 93
waited 93
waited 93
waited 93
waited 94
waited 93
waited 93
waited 93
waited 93
waited 94
waited 94
waited 94
waited 94
waited 94
waited 95
waited 96
waited 96

Safari 5.1.5:

waited 100
waited 104
waited 104
waited 103
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104

Chrome 19.0.1084.52:

waited 101
waited 103
waited 103
waited 104
waited 104
waited 103
waited 103
waited 103
waited 103
waited 103
waited 103
waited 103
waited 103
waited 103
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104

答案 1 :(得分:1)

JavaScript是同步的。浏览器会将您的setTimeout添加到队列中并在

之后执行它们
  1. 倒计时已结束
  2. 它已完成倒计时结束时队列中的任何其他任务。

答案 2 :(得分:1)

我编写了以下函数,以确保我的代码至少在给定的毫秒数后执行。我用它而不是setTimeout

mySetTimeout=function(f,t){
    var endTime=new Date().valueOf()+t;
    setTimeout(function(){
        var now=new Date().valueOf();
        if(now<endTime){
            mySetTimeout(f,endTime-now);
        }else{
            f();
        }
    },t);
};