1

I have written a jQuery plugin and all is well except the script pauses when you switch to a different tab. The body of the script is a setInterval() with a 1ms delay.

    var count = setInterval( function() {
            if (iMil <= 0) {
                if (iS == 0) {
                    if (iMin == 0) {
                        if (iH == 0) {
                            // DONE
                            milliseconds.text(0);
                            clearInterval(count);
                        } else {
                            iH--;
                            iMin = 59;
                            iS = 59;
                            iMil = 999;
                        }
                    } else {
                        iMin--;
                        iS = 59;
                        iMil == 999;
                    }
                } else {
                    iS--;
                    iMil = 999;
                }
            } else {
                iMil-=4; // Make up for ms lost doing calculations
            }
            hours.text(iH);
            minutes.text(iMin);
            seconds.text(iS);
            if (iMil >= 10 && iMil < 100) {
                milliseconds.text('0'+iMil);
            } else if (iMil >= 0 && iMil < 10) {
                milliseconds.text('00'+iMil);
            } else if (iMil == -1) {
                milliseconds.text('000');
            } else {
                milliseconds.text(iMil);
            }
        }, 1 );

Is there a way to run this regardless which tab you are on?

Spedwards
  • 4,167
  • 16
  • 49
  • 106
  • You can't make this run in background - browsers don't work like that. You can't even rely on a 1ms tick when the tab is in foreground. The way to handle this is to note the start time, calculate the elapsed time when your `setInterval` function is called and work out what need to be done from there. –  Jun 02 '14 at 05:14
  • @MikeW What about those Javascript games that you can actually see run in the background. – Spedwards Jun 02 '14 at 05:18
  • If you can see them they're not on a tab in the same browser. –  Jun 02 '14 at 05:20
  • @MikeW I can see the page title (on the tab) change every second. – Spedwards Jun 02 '14 at 05:26

1 Answers1

3

For power management reasons, many browsers will slow down or stop interval timers when the page is not in the foreground.

As I said in my earlier response to you for another question using this same code, you should NOT be maintaining your own time count because setInterval() is not an exact timer (as you've discovered).

Instead, you should store the start time and then get the current time on each timer tick and calculate the actual elapsed time. You will not have any issues with tabs going to the background if you do it that way and each time your timer is called, you will always display the correct time.

The interval timer will be a display update timer, not a timer to keep track of an exact amount of time.

So, if you want to show elapsed time, you would do something like this:

function startTimer() {
    var startTime = new Date().getTime();
    var timer = setInterval(function() {
        var elapsedMilliseconds = new Date().getTime() - startTime;
        // now do whatever you want with the elapsedMilliseconds

    }, 1);
}
Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I don't think I can do this for my situation. See my working demo: http://spedwards.github.io/projects/countdown/ – Spedwards Jun 03 '14 at 06:57
  • 1
    I'm not sure why you can't do this? You certainly can't use `setInterval()` as an accurate timer with 1ms resolution. It just isn't that. And, the browser can even slow it down if it wants to in order to save battery life. It's a recurring interval with an approximate time. That's the best you can make of it. If you want to display accurate time, you have to use the system time to keep track of time, not the counting of `setInterval()` ticks. – jfriend00 Jun 03 '14 at 07:00
  • Well I've changed it from 1ms to 10ms but I'll see if I can figure out a way to make it work. – Spedwards Jun 03 '14 at 07:05
  • The way I've got my script set out, I cannot use this. – Spedwards Jun 03 '14 at 07:32
  • @Spedwards this is the best solution to your problem. If your script needs to be reworked to follow this pattern, rework it. – Rory McCrossan Jun 03 '14 at 08:27