1

I have created a self-repeating function using JavaScript, however when I navigate to another tab open in my browser and go back to the tab containing the function; the function is repeating at a much faster pace than specified; can anybody shed any light on why this may happen?

Example of JavaScript Used:

function aFunction() {
    var aFunctionVar;
    clearTimeout(aFunctionVar);
    aFunctionVar = setTimeout(aFunction,8000);
    if (condition) {
        //More code to run...
        return false; 
    }
    if (condition) {
        //More code to run...
        return false; 
    } 
};
aFunction();
Tom Platts
  • 33
  • 5
  • Can you show the code for this function? – Nick Rolando Aug 31 '11 at 00:55
  • Nothing to do with your problem, but please change: `setTimeout("aFunction()",8000);` to `setTimeout(aFunction,8000);`. Much better to use direct references to functions rather than eval parsed strings. – jfriend00 Aug 31 '11 at 01:22
  • That `clearTimeout(aFunctionVar);` isn't doing anything. The variable `aFunctionVar` would be undefined at that point - it doesn't retain its value from the previous call; it needs to be declared outside the function for that to work. Having said that, calling `clearTimeout()` after the timeout happens doesn't do anything anyway - the only reason to use it is to cancel a timeout that has been "queued" but not yet executed. Is it just a typo that your function as it now reads has `setTimeout()` twice? – nnnnnn Aug 31 '11 at 02:30
  • @nnnnnn As I said in a comment below it was a typo, by the way any suggestion as to what the problem could be and possible ways of solving it? Thankyou. – Tom Platts Sep 01 '11 at 03:07

2 Answers2

3

If your code is using setInterval() and you are running in a browser like Firefox or Chrome, then this is because those browsers are slowing down timers in background tabs while they are in the background (and thus not displayed). When you then bring it back to the foreground, it tries to catch them up. There are a number of possible work-arounds. The best idea is to stop your timer when your browser window is no longer displayed and restart it when the window is displayed again.

On the Chromium blog, Google said:

In the forthcoming Chrome 11 release, we plan to reduce CPU consumption even for pages that are using setTimeout and setInterval. For background tabs, we intend to run each independent timer no more than once per second. This change has already been implemented in the Chrome dev channel and canary builds.

Possible ways to work-around this:

  • Stop your timer/animation when the window is not visible. Restart the timerwhen the window becomes visible.
  • Instead of setInterval, use setTimeout and then just reset the setTimeout each time it fires to create your own repeating interval.
  • Slow your timers down so they don't run afoul of this.

The best option is probably to figure out when to just stop and then restart the timers.

Similar question here: Chrome: timeouts/interval suspended in background tabs?.

FYI, Chrome has new experimental API for detecting page visibility for just this reason. You can read about it here: http://code.google.com/chrome/whitepapers/pagevisibility.html. it helps solve the issue when your page is visible, but doesn't have focus.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Really informative answer, thankyou; but I have used the setTimeout method and cleared the timeout everytime the function is run; yet the function still simultaneously repeats itself once back in view. – Tom Platts Aug 31 '11 at 01:43
2

Don't use setInterval. Use a setTimeout at the end of the function to have it call itself. Generally your code won't keep running in the background when another tab is active, but with setInterval some browsers try to "catch up" on missed calls once your tab is made active again - which results in the faster operation you describe. Another option is to implement your own pause by reacting when your page loses and regains focus.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • I did originally use the setInterval method but as your answer states realised it would at some point be forced to run many times simultaneously due to background tab timer restrictions but I'm currently using the setTimeout method; thanks anyway. – Tom Platts Aug 31 '11 at 01:17
  • Your function as it now reads has `setTimeout()` twice. If that is just a typo here at SO then no problem, but if your real code is like that it would explain your problem since every execution of the function would queue up two more executions for later... – nnnnnn Aug 31 '11 at 02:37
  • Yeah its just a typo sorry about that. I decided to update the code you see. – Tom Platts Sep 01 '11 at 03:05