jQuery/JavaScript:我的递归setTimeout函数在选项卡失效时加速

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

本文关键字:选项 失效 加速 函数 setTimeout JavaScript 我的 递归 jQuery      更新时间:2023-09-26

我在构建这个jQuery幻灯片插件时遇到了一个奇怪的小难题。

这不是什么花哨的,我写的代码迄今为止工作很好,但我注意到,当我离开网站运行并切换到一个新的选项卡,并继续浏览网页在这个其他选项卡(Chrome for Mac在我的情况下),当我回到我的网站,setTimeout调用似乎有加速,而不是等待计时器完成火灾事件,它连续火灾。

下面是我的(简化)代码:
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 = '';
}

所以应该发生的是,在动画结束时,计时器重新连接到另一个setTimeout调用,这样它就变成了一个连续的幻灯片(这工作得很好,直到你离开选项卡。

一旦你离开选项卡,并返回到选项卡与幻灯片似乎,3000 ms定时器已减少到立即调用,现在的时刻动画完成下一个开始没有延迟在所有。

任何关于为什么会发生这种情况以及如何解决它的想法将不胜感激。

谢谢你的阅读,

Jannis

一些浏览器(如Chrome)在标签处于非活动状态时急剧减慢循环计时器,然后,当标签再次激活时,它们试图"赶上",以便发生相同数量的实际计时器事件。我所能想到的解决方法就是当标签页处于非活动状态时完全停止幻灯片显示,当它激活时重新开始。

您尝试过间隔时间吗?对于递归,只需调用nextSlide()函数作为它自己的回调:

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

那么它只是一个开始和停止间隔的问题:

var slideshow;
function startSlideshow()
{
    slideshow = setInterval(nextSlide(),3000);
}
function stopSlideshow()
{
    clearInterval(slideshow);
    inner.stop();
}