4

Today I was introduced to the world of Web Workers in JavaScript. This made me rethink about timers. I used to program timers the ugly way, like this.

var time = -1;
function timerTick()
{
    time++;
    setTimeout("timerTick()",1000);
    $("#timeI").html(time);
}

I know this could be improved by saving the date when you start the timer, but I've never been a fan of that.

Now I came up with a method using Web Workers, I did a little benchmark and found it much more reliable. Since I am not an expert on JavaScript I would like to know if this function works correct or what problems it might have thanks in advance.

My JavaScript code (please note I use JQuery):

$(function() {
    //-- Timer using web worker. 
    var worker = new Worker('scripts/task.js'); //External script
    worker.onmessage = function(event) {    //Method called by external script
        $("#timeR").html(event.data)
    };
};

The external script ('scripts/task.js'):

var time = -1;
function timerTick()
{
    time++;
    setTimeout("timerTick()",1000);
    postMessage(time);
}
timerTick();

You can also view a live demo on my website.

7
  • 3
    setInterval is not very reliable. Commented Nov 30, 2011 at 20:31
  • 9
    Don't pass a string to setTimeout or setInterval. Always use an explicit function reference or anonymous function: setTimeout(timerTick) or setTimeout(function() { timerTick(123); } ) Commented Nov 30, 2011 at 20:31
  • @Kenaniah: That's not a good idea. At least with setTimeout, you could test for fluctuation in the timing, and adjust the next call. Commented Nov 30, 2011 at 20:35
  • @pimvdb Why is it not reliable? The only shortcoming I can think of is that it isn't gauranteed to fire after the interval if other JS is already running (in the same context). But setTimeout has the same problem. Commented Nov 30, 2011 at 20:36
  • @Matt I think (well, I hope :-) that his point was that none of the timing options in a browser are reliable. Commented Nov 30, 2011 at 20:41

2 Answers 2

11

If you're trying to reliably display seconds ticking by, then the ONLY reliable way to do that is to get the current time at the start and use the timer ONLY for updating the screen. On each tick, you get the current time, compute the actual elapsed seconds and display that. Neither setTimeout() nor setInterval() are guaranteed or can be used for accurately counting time.

You can do it like this:

var start = +(new Date);
setInterval(function() {
    var now = +(new Date);
    document.getElementById("time").innerHTML = Math.round((now - start)/1000);
}, 1000);

If the browser gets busy and timers are erratically spaced, you may get a slightly irregular update on screen, but the elapsed time will remain accurate when the screen is updated. Your method is susceptible to accumulating error in the elapsed time.

You can see this work here: http://jsfiddle.net/jfriend00/Gfwze/

Sign up to request clarification or add additional context in comments.

8 Comments

Nice code! I never saw this coded that short and simple. Thanks for sharing.
Uhm, I know that it's kind of late to answer that but I want to point out that the code above might not actually be precise. You don't get to see it because of Math.round but every interval will be a few milliseconds off. In my opinion it's better to use setTimeout, measure the time difference and have the possibility to adjust for the delay that might happen inside the function.
When I run your code and I change my system date, it affects the seconds by adding or subtracting the difference in time. Is there a way to make this solution independent of the client's system date?
@KidDiamond - no, not really for accurate time. You could (through some elaborate means) probably detect if the system time has been changed by the user (to perhaps prevent cheating at some time dependent operation), but Javascript does not expose a clock that is independent of the time that the user can set (most operating systems have such a clock, but JS doesn't provide access to it).
See also: this fork of the above jsfiddle which shows the difference. It strays even faster if you alt-tab for a bit. jsfiddle.net/mxbbm2L0/1
|
0

The most accurate timer would be a comparison of two time stamps. You could increase the precision of your timer by updating more frequently (such as every 100ms). I prefer using setInterval() over setTimeout().

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.