Frage jQuery / JavaScript: Meine rekursive setTimeout-Funktion beschleunigt sich, wenn die Registerkarte inaktiv wird


Ich habe ein seltsames kleines Dilemma in diesem jQuery Slideshow Plugin, das ich gerade erstelle.

Es ist nichts Schickes und der Code, den ich bisher geschrieben habe, funktioniert großartig, aber ich habe bemerkt, dass wenn ich die Seite aktiv lasse und zu einem neuen Tab wechsle und auf dieser anderen Registerkarte weiter im Internet surfe (Chrome für Mac in meinem Fall) dass, wenn ich auf meine Seite zurückkomme, die setTimeout Anruf scheint zu beschleunigen und anstatt auf den Timer zu warten, um das Ereignis zu beenden, feuert es ununterbrochen.

Hier ist mein (vereinfacht) 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 = '';
}

Was passiert, ist, dass am Ende der Animation der Timer mit einem anderen verbunden wird setTimeout Rufen Sie an, so dass es eine fortlaufende Diashow wird (und das funktioniert gut, bis Sie die Registerkarte verlassen.

Sobald Sie die Registerkarte verlassen und zu der Registerkarte mit Diashow zurückkehren, scheint es, dass die 3000 ms Der Timer wurde so reduziert, dass er sofort aufgerufen wird und jetzt, wenn die Animation beendet ist, startet der nächste ohne Verzögerung.

Irgendwelche Ideen, warum dies geschieht, wie es gelöst werden kann, würden sehr geschätzt werden.

Danke fürs Lesen,

Jannis


5
2017-07-08 01:24


Ursprung


Antworten:


Einige Browser (z. B. Chrome) verlangsamen die Timer, wenn die Registerkarte inaktiv wird, und wenn die Registerkarte wieder aktiv wird, versuchen sie, "aufzuholen", so dass die gleiche Anzahl von tatsächlichen Timer-Ereignissen aufgetreten ist. Alles, was ich mir als Workaround vorstellen kann, ist, dass Sie die Diashow vollständig anhalten, wenn der Tab inaktiv wird, und ihn erneut startet, wenn er aktiv ist.


6
2017-07-08 01:28



Hast du Zeitüberschreitungen probiert? Um auch rekursiv zu sein, rufen Sie einfach die Funktion nextSlide () als eigenen Callback auf:

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()
    });

}

Dann geht es nur darum, ein Intervall zu starten und anzuhalten:

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

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

2
2017-07-08 01:44