45

I want to create a timer that once it reaches a certain point, the timer resets, and then starts over.

Right now, I've got the loop set up, and as a test I want it to reset after 5000 ms (5 seconds). But the counter goes all haywire.

WIP Demo here: http://jsfiddle.net/stursby/wUHA3/

stursby
  • 871
  • 2
  • 12
  • 23

2 Answers2

92

Instead of setTimeout, consider using setInterval. It will repeat automatically until you clear the interval.

setInterval(myMethod, 5000);

function myMethod( )
{
  //this will repeat every 5 seconds
  //you can reset counter here
}
Ken Browning
  • 28,693
  • 6
  • 56
  • 68
keyboardP
  • 68,824
  • 13
  • 156
  • 205
  • 1
    I agree, just to point out the reason he is having the issue described is because of the line `var diff = (new Date().getTime() - start) - time;` there is no need for that line. He should be doing `window.setTimeout(instance, 100);` instead of `window.setTimeout(instance, (100 - diff));`. And his issue is resolved. – Chad Dec 29 '11 at 02:00
  • You could post that as an answer because it's just as valid. OP can then decide if that method might suit their overall program. Whilst setInterval usually makes sense in a case like this, your code directly fixes the issue at hand. – keyboardP Dec 29 '11 at 02:02
  • 5
    For completeness, to set the interval: `var timer = setInterval(function(){ doStuff() }, 1000);` To subsequently clear the interval (and stop the timer): `clearInterval(timer);` – Steven Jun 05 '17 at 07:28
6

I agree with keyboardP that you should probably be using setInterval instead of setTimeout. However, to answer your original question the reason you are having issues with the timer is because of your repetition logic. Don't use:

var diff = (new Date().getTime() - start) - time;
window.setTimeout(instance, (100 - diff));

You don't need to try and account for execution time (which I assume is what you were trying to do with diff). Just assume it is negligible and use:

setTimeout(instance, 100);

And your issue is resolved, as you can see in this jsFiddle.

Chad
  • 19,219
  • 4
  • 50
  • 73
  • is there an easy way for this to increment by 1's instead of 100's? For example, 2.1 seconds is 2100, is there a way to get to more decimals like 2.154 seconds, or 2154 on the timer? – stursby Dec 29 '11 at 18:54
  • well the accuracy will not be exact to the millisecond. Browsers evaluate timeouts/intervals differently. As an average every 13ms a timeout is evaluated. SO that is about as specific as you can get, depending on the browser. – Chad Dec 29 '11 at 19:00
  • Okay, well I won't need to visually display the timer in ms, I just want the accuracy of 4 decimal places, because the timer is going to trigger other events that will need to synch up based on the timer and 2.4 seconds (2400 versus 2418) makes a difference. here's a WIP demo http://jsfiddle.net/stursby/zFYUT/5/ I still need to add looping, but that's essential what I'm trying to do (in the end, it won't be visual though) – stursby Dec 29 '11 at 19:08
  • Like I said, timeouts and intervals are evaluated differently in each browser. Usually around every 14ms they are evaluated. Meaning, if you do a delay of 1ms, it may actually take anywhere from 1 to 15. so your timer will not be accurate to a millisecond. Probably not even to 10ms, but it would be pretty close in orders of 100ms. Best you can do is if you have to trigger an event at 2418, you trigger it once the time ellapsed has *exceeded* 2418; thats about the best you can do. – Chad Dec 29 '11 at 21:33