开发者

setTimeout and difference in Time

I have a loop kind of like this

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);
    }
}

When setTimeout is called, the time that has passed during the updateTime does not seem to of passed when diffTime is updated. Here, I have set it to be 1000 / 60 milliseconds, but I get numbers there are less than that, which doesn't make sense. It should be more than or equal to. Why is it doing that?

In response to davin: I don't use setInterval because it stacks the calls http://bonsaiden.github.com/JavaScript-Garden/#other.timeouts.

The while reduces the diffTime into 1000 / 60 blocks of time, especially when it is greater than 16 ms. Modulus operator is expensive.

The reason I know that the updateTime hasn't passed is that print out the diffTime before I manipulate it. The number always comes out less than updateTime given to setTimeout.

Log:

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

Looking at the updateTime and the before diffTime, the timing doesn't make sense. For example I have 15.666666666666668, but the difference in time after it is 12.

New Log:

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
updateW开发者_JAVA百科ithoutTimer
- 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

Here is another log that does not do it only on the first tick. When I have tested it, it seems to work like setTimeout(func), so no millisecond elapse. The delay seems to be the browser. Currently I am using Mozilla Aurora 6.0a and Google Chrome 14.0.803 dev. I thought I would just recheck both browsers and I go the same result in Aurora, but Chrome worked as expected. Oddly I tested it before hand and it didn't work correctly. I assume it is a bug in Aurora. I have submitted a bug report to mozilla.

I assign lastTimeUpdate because I want to find out how long it has taken to get to this frame and how long the frame has taken, so I can process it accordingly.

Update: Here is the bug report: https://bugzilla.mozilla.org/show_bug.cgi?id=668765. Apparently, setTimeout will try to do the right thing. If it has recently fired late it will try to fire early.


Your code doesn't make much sense to me. What is that while loop doing? Why not just have a modulus operator after rounding and do it in 1 step? Why are you subtracting this difference in such a strange manner? On what basis do you claim that the time hasn't passed? I see no checking of any value.

Of course you're getting values that are <= updateTime = 1000/60 ~ 16, because you set the interval to be such: You loop until diffTime < updateTime and then execute the new timer for a delay of updateTime - diffTime. The maths is simple: 0 < updateTime - diffTime < updateTime.

It looks like you want to update every so often. That's why they invented setInterval. You're reinventing the wheel which is both unnecessary and less reliable than the browser's implementation.

UPDATE

I presume you're not an assembly programmer. The modulus operator will perform a constant number of arithmetic operations, say 4 worst-case. Your loop will perform almost the same number of operations each iteration, since it has to perform the condition check, the subtraction, the assignment and a branch (which can itself be expensive). So if your loop does even 2 iterations its already more expensive than a modulus operator.

Regarding your times, you say that it happens "all the time" although from that output it looks like it happens only the first time. I ran the same code and the numbers made sense. What platform are you running on? Does this ever happen other than on the first tick? Does it happen every time on the first tick? Some more information would be helpful.

As an aside, you're overestimating your diffTime because you're setting lastUpdateTime before you do a whole bunch of things. What you should be doing is assigning lastUpdateTime at the point of setTimeout.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜