setTimeout和时间差

时间:2011-06-30 10:59:45

标签: javascript

我有一个像这样的循环

var lastUpdateTime = (new Date()).getTime(),
    diffTime = 0,
    i = 0;

function update() {
    var updateTime = 1000 / 60,
        now;

    // do some stuff...

    console.log("update");
    console.log(" - i:" + i);

    now = (new Date()).getTime();
    diffTime = now - lastUpdateTime;
    lastUpdateTime = now;

    console.log(" - - before diffTime:" + diffTIme);

    while (diffTime >= updateTime) {
        diffTime -= updateTime;
    }

    console.log(" - - after diffTime:" + diffTime);

    updateTime -= diffTime;

    console.log(" - - updateTime:" + updateTime);

    if ( i < 10) {
        i += 1;
        setTimeout(update, updateTime);
    }
}

调用setTimeout时,更新diffTime时似乎没有传递updateTime期间传递的时间。在这里,我将其设置为1000 / 60毫秒,但是我得到的数字少于那个,这没有意义。它应该大于或等于。为什么这样做?

回应davin: 我不使用setInterval,因为它会堆叠调用http://bonsaiden.github.com/JavaScript-Garden/#other.timeouts

while将diffTime缩减为1000 / 60个时间段,特别是当它大于16毫秒时。模数算子很昂贵。

我知道updateTime未通过的原因是在我操作它之前打印出diffTime。该数字始终低于updateTime的{​​{1}}。

日志:

setTimeout

查看update - i:0 - - before diffTime:1 - - after diffTime:1 - - updateTime:15.666666666666668 update - i:1 - - before diffTime:12 - - after diffTime:12 - - updateTime:4.666666666666668 update - i:2 - - before diffTime:54 - - after diffTime:3.999999999999993 - - updateTime:12.666666666666675 update - i:3 - - before diffTime:13 - - after diffTime:13 - - updateTime:3.666666666666668 update - i:4 - - before diffTime:11 - - after diffTime:11 - - updateTime:5.666666666666668 update - i:5 - - before diffTime:14 - - after diffTime:14 - - updateTime:2.666666666666668 updateTime,时机没有意义。例如,我有before diffTime,但是15.666666666666668之后的时间差异。

新记录:

12

这是另一个仅在第一个刻度上不执行此操作的日志。当我测试它时,它似乎像updateWithoutTimer - i:0 - - before diffTime:2 - - after diffTime:2 - - updateTime:14.666666666666668 updateWithoutTimer - i:1 - - before diffTime:5 - - after diffTime:5 - - updateTime:11.666666666666668 updateWithoutTimer - i:2 - - before diffTime:8 - - after diffTime:8 - - updateTime:8.666666666666668 updateWithoutTimer - i:3 - - before diffTime:86 - - after diffTime:2.66666666666665 - - updateTime:14.000000000000018 updateWithoutTimer - i:4 - - before diffTime:24 - - after diffTime:7.333333333333332 - - updateTime:9.333333333333336 updateWithoutTimer - i:5 - - before diffTime:34 - - after diffTime:0.6666666666666643 - - updateTime:16.000000000000004 updateWithoutTimer - i:6 - - before diffTime:24 - - after diffTime:7.333333333333332 - - updateTime:9.333333333333336 updateWithoutTimer - i:7 - - before diffTime:27 - - after diffTime:10.333333333333332 - - updateTime:6.333333333333336 updateWithoutTimer - i:8 - - before diffTime:14 - - after diffTime:14 - - updateTime:2.666666666666668 updateWithoutTimer - i:9 - - before diffTime:2 - - after diffTime:2 - - updateTime:14.666666666666668 updateWithoutTimer - i:10 - - before diffTime:2 - - after diffTime:2 - - updateTime:14.666666666666668 一样工作,所以没有经过毫秒。延迟似乎是浏览器。目前我使用的是Mozilla Aurora 6.0a和Google Chrome 14.0.803 dev。 我以为我会重新检查两个浏览器,我在Aurora中得到相同的结果,但Chrome按预期工作。奇怪的是,我事先测试了它并且它无法正常工作。我认为这是Aurora中的一个错误。我已经向mozilla提交了一份错误报告。

我指定了lastTimeUpdate,因为我想知道到达这个帧需要多长时间以及帧已经花了多长时间,所以我可以相应地处理它。

更新 以下是错误报告:https://bugzilla.mozilla.org/show_bug.cgi?id=668765。显然,setTimeout(func)会尝试做正确的事情。如果它最近被解雇,它会尽早开火。

1 个答案:

答案 0 :(得分:1)

你的代码对我没有多大意义。 while循环在做什么?为什么不在舍入后只使用模数运算符并在一步中完成?你为什么以这种奇怪的方式减去这种差异?在什么基础上你声称时间还没有过去?我看不到任何价值的检查。

当然,您获得的值为<= updateTime = 1000/60 ~ 16,因为将时间间隔设置为:您循环到diffTime < updateTime然后执行新计时器延迟updateTime - diffTime。数学很简单:0 < updateTime - diffTime < updateTime

看起来你想要经常更新。这就是他们发明setInterval的原因。你正在重新发明轮子,这比浏览器的实现更加不必要且不太可靠。

<强>更新

我认为你不是一个汇编程序员。模数运算符将执行恒定数量的算术运算,例如4个最坏情况。你的循环将执行几乎相同数量的操作每次迭代,因为它必须执行条件检查,减法,赋值和分支(这本身可能很昂贵)。因此,如果你的循环甚至进行了2次迭代,那么它已经比模数运算符更昂贵了。

关于你的时间,你说它“一直”发生,虽然从那个输出看起来它只是第一次发生。我运行相同的代码,数字是有道理的。你在运行什么平台?除了第一次打勾之外,这会不会发生?第一次打勾时是否每次都会发生?更多信息会有所帮助。

顺便说一下,你高估了diffTime因为你在做一大堆事情之前设置了lastUpdateTime。您应该做的是在lastUpdateTime点分配setTimeout