简体   繁体   中英

jQuery/JavaScript: My recursive setTimeout function speeds up when tab becomes inactive

I've got an odd little dilemma in this jQuery slideshow plugin that I am building.

It's nothing fancy and the code I have written to date is working great however I have noticed that when I leave the site running and switch to a new tab and continue browsing the web in this other tab (Chrome for Mac in my case) that when I return to my site, the setTimeout call seems to have speed up and instead of waiting for the timer to finish the fire the event, it fires continuously.

Here is my (simplified) code:

var timer;
var counter;
var slides; // collection of all targeted slides.

// animate to the next slide
function nextSlide() {

    // stop timer
    methods.stopTimer();

    // increase counter
    counter++;
    if ( counter > slides.length-1 ) { counter = 0; } // if counter is greater than the amount of slides, back to the start.

    // inner = container to be animated
    // in the complete callback restart the timer.
    inner.animate({
        'left': '-'+slides.eq( counter ).position().left
    }, {
        duration : settings.animationSpeed,
        easing  : 'easeInOutExpo',
        complete : startTimer()
    });


}
// timer functions.
function startTimer() {
    if ( timer === '' ) {
        timer = setTimeout( function() {
            nextSlide();
        } , 3000 );
    }
}
function stopTimer() {
    clearTimeout( timer );
    timer = '';
}

So what should happen is that at the end of the animation, the timer gets reattached with another setTimeout call so that it becomes a continuous slideshow (and this works just fine until you leave the tab.

Once you leave the tab and return to the tab with slideshow it seems that the 3000 ms timer has been reduced to invoke instantly and now the moment the animation finishes the next one starts with no delay at all.

Any ideas on why this is happening on how it can be solved would be much appreciated.

Thanks for reading,

Jannis

Some browsers (like Chrome) drastically slow down recurring timers when the tab goes inactive and then, when the tab comes active again, they try to "catch up" so that the same number of actual timer events has occurred. All I can think of as a work-around is for you to stop the slideshow entirely when the tab goes inactive and start it again when it comes active.

Instead of timeouts have you tried intervals? Also for it to be recursive, just call the nextSlide() function as its own callback:

var counter = 1;

// animate to the next slide
function nextSlide() {

    // increase counter
    counter++;

    // if counter is greater than the amount of slides, back to the start.
    counter =  ( counter > slides.length-1 ) ? 0 : counter;

    // inner = container to be animated
    // in the complete callback restart the timer.
    inner.animate(
    {
        'left': '-' + slides.eq( counter ).position().left
    }, 
    {
        duration : settings.animationSpeed,
        easing  : 'easeInOutExpo',
        complete : nextSlide()
    });

}

Then it's just a matter of starting and stopping an interval:

var slideshow;
function startSlideshow()
{
    slideshow = setInterval(nextSlide(),3000);
}

function stopSlideshow()
{
    clearInterval(slideshow);
    inner.stop();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM