tags:

views:

2764

answers:

9

As far as I can tell, these two pieces of javascript behave the same way:

Option A:

function myTimeoutFunction()
{
    doStuff();
    setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

Option B:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

Is there any difference? Which do you use and why?

+23  A: 

The difference is subtle, I believe the setInterval code executes every 1000ms exactly, while the setTimeout waits 1000ms, runs the function, which takes some ms, then sets another timeout. So the wait period is actually greater than 1000ms.

David Caunt
Andy had a similar suggestion.Hypothetically, does this mean that if the method takes more than 1000ms to execute, you can have more than one running simultaneously?
Damovisa
Theoratically, yes. In practise, no since Javascript does not support multithreading. If your code takes longer than 1000ms, it will freeze the browser.
Kamiel Wanrooij
Technically, the code wont execute *exactly* every 1000ms, since it depends on the resolution of the timer and whether other code is already executing. Your point still stands though.
Matthew Crumley
Interesting... thanks guys.
Damovisa
Note an interval can still be delayed or dropped if you're failing to service it in time (see below).
bobince
A: 

I use setTimeout.

Apparently the difference is setTimeout calls the method once, setInterval calls it repeatdly.

Here is a good article explaining the difference: Tutorial: JavaScript timers with setTimeout and setInterval

Bravax
Yep, I got that difference, but the two pieces of code I've provided should then do the same thing...
Damovisa
Ummm yes... I would have thought... but according to dcaunt and his vote count that's not quite what happens.
Bravax
+7  A: 

The setInterval makes it easier to cancel future execution of your code. If you use setTimeout, you must keep track of the timer id in case you wish to cancel it later on.

var timerId = null;
function myTimeoutFunction()
{
    doStuff();
    timerId = setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

// later on...
clearTimeout(timerId);

versus

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
var timerId = setInterval(myTimeoutFunction, 1000);

// later on...
clearInterval(timerId);
Kamiel Wanrooij
Nice, I didn't consider cancelling...
Damovisa
I don't see how you are not keeping track of the timer id in the case of setInterval. It's just pulled out of the function.
Kekoa
+2  A: 

I find the setTimeout method easier to use if you want to cancel the timeout:

function myTimeoutFunction() {
   doStuff();
   if (stillrunning) {
      setTimeout(myTimeoutFunction, 1000);
   }
}

myTimeoutFunction();

Also, if something would go wrong in the function it will just stop repeating at the first time error, instead of repeating the error every second.

Guffa
A: 

Both setInterval and setTimeout return a timer id that you can use to cancel the execution, that is, before the timeouts are triggered. To cancel you call either clearInterval or clearTimeout like this:

var timeoutId = setTimeout(someFunction, 1000);
clearTimeout(timeoutId);
var intervalId = setInterval(someFunction, 1000),
clearInterval(intervalId);

Also, the timeouts are automatically cancelled when you leave the page or close the browser window.

Helgi
+4  A: 

If you would like some good details on how timers in JS work, John Resig wrote a good article on this topic

Rafael
+38  A: 

Is there any difference?

Yes. A Timeout executes a certain amount of time after setTimeout() is called; an Interval executes a certain amount of time after the previous interval fired.

You will notice the difference if your doStuff() function takes a while to execute. For example, if we represent a call to setTimeout/setInterval with ‘.’, a firing of the timeout/interval with ‘*’ and JavaScript code execution with ‘[-----]’, the timelines look like:

Timeout:

.    *  .    *  .    *  .    *  .
     [--]    [--]    [--]    [--]

Interval:

.    *    *    *    *    *    *
     [--] [--] [--] [--] [--] [--]

The next complication is if an interval fires whilst JavaScript is already busy doing something (such as handling a previous interval). In this case, the interval is remembered, and happens as soon as the previous handler finishes and returns control to the browser. So for example for a doStuff() process that is sometimes short ([-]) and sometimes long ([-----]):

.    *    *    •    *    •    *    *
     [-]  [-----][-][-----][-][-]  [-]

• represents an interval firing that couldn't execute its code straight away, and was made pending instead.

So intervals try to ‘catch up’ to get back on schedule. But, they don't queue one on top of each other: there can only ever be one execution pending per interval. (If they all queued up, the browser would be left with an ever-expanding list of outstanding executions!)

.    *    •    •    x    •    •    x
     [------][------][------][------]

x represents an interval firing that couldn't execute or be made pending, so instead was discarded.

If your doStuff() function habitually takes longer to execute than the interval that is set for it, the browser will eat 100% CPU trying to service it, and may become less responsive.

Which do you use and why?

Chained-Timeout gives a guaranteed slot of free time to the browser; Interval tries to ensure the function it is running executes as close as possible to its scheduled times, at the expense of browser UI availability.

I would consider an interval for one-off animations I wanted to be as smooth as possible, whilst chained timeouts are more polite for ongoing animations that would take place all the time whilst the page is loaded. For less demanding uses (such as a trivial updater firing every 30 seconds or something), you can safely use either.

In terms of browser compatibility, setTimeout predates setInterval, but all browsers you will meet today support both, except for the utterly abysmal IE Mobile, which doesn't support setInterval. But then chances are it doesn't support anything else you're using either.

bobince
That's an awesome answer - thanks heaps!
Damovisa
But does the reason of choice between Interval and Timeout hold true even non-browser platforms, like for instance WebOS or JIL?
LVS
A nice way of doing chained timeouts on anonymous functions:setTimeout(function(){ setTimeout(arguments.callee,10)},10)
Justin Meyer
In terms of browser compatibility, although all browsers provide both methods, their performance is different.
unigg
A: 

This article says that you should avoid setInterval if possible, especially since you can replicate its behavior with setTimeout and get some additional benefits along the way.

John Sheehan
+1  A: 

It seems that no one in this thread has actually tested setInterval's ability to keep time. If you had, you would have found that not two browsers do exactly the same. But they are all unreliable for timekeeping.

Firefox tries to keep on schedule, except for when it misses an iteration, then it just skips it, but you don't need to be anywhere near 100% CPU load for that to happen.

IE does sorta the same as Firefox, except that it only works as long as it is fed a time that is divisible by 15.625 (1/64 second). Otherwise it rounds the number up to meet the aforementioned criteria.

Opera, Safari and Chrome as far as I can tell all just execute too slowly.

If you just need some update to run once in a while setInterval is fine, but if you need actual timekeeping there is no way around keeping on calling new Date().getTime() to get the actual time.

eBusiness