7

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

看看这个小提琴。本质上,100 毫秒的 setTimeout 似乎在 80 毫秒到 110 毫秒之间运行。根据John Resig 对 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);
}

这是一个古怪的输出示例:

在此处输入图像描述

这是我的浏览器信息:

在此处输入图像描述

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

更多信息

我通过使用 setInterval() 并检查每个增量以查看所需时间是否已经过去来解决该问题。看到这个小提琴

但是,我仍然很想知道是否有人可以阐明问题的根源

4

3 回答 3

3

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

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

正如您发布的链接所述,既不setTimeout也不setInterval承诺他们将在正确的时间执行。但是,使用setInterval,您将受益于计时器循环,如果它落后太远,您可以通过追赶来“纠正自己”,因此无论您尝试做什么,它可能更合适。

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

火狐 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

铬 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
于 2012-06-04T01:38:22.517 回答
1

JavaScript 是同步的。浏览器会将您setTimeout的 s 添加到队列中并在之后执行它们

  1. 倒计时结束
  2. 倒计时结束时,它已完成队列中的任何其他任务。
于 2012-06-04T16:34:58.677 回答
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);
};
于 2013-05-25T19:36:11.673 回答