简体   繁体   English

使用 setInterval 时,如果我在 Chrome 中切换标签页并返回 go,slider 会疯狂追赶

[英]When using setInterval, if I switch tabs in Chrome and go back, the slider goes crazy catching up

I have a jQuery slider on my site and the code going to the next slide is in a function called nextImage.我的网站上有一个 jQuery slider,下一张幻灯片的代码位于名为 nextImage 的 function 中。 I used setInterval to run my function on a timer, and it does exactly what I want: it runs my slides on a timer.我使用 setInterval 在计时器上运行我的 function,它完全符合我的要求:它在计时器上运行我的幻灯片。 BUT, if I go to the site in Chrome, switch to another tab and return, the slider runs through the slides continuously until it 'catches up'.但是,如果我 go 到 Chrome 中的网站,切换到另一个选项卡并返回,slider 会连续运行幻灯片,直到它“赶上”。 Does anyone know of a way to fix this.有谁知道解决这个问题的方法。 The following is my code.以下是我的代码。

setInterval(function() {
nextImage();
}, 8000);

How to detect when a tab is focused or not in Chrome with Javascript? 如何使用 Javascript 在 Chrome 中检测标签何时聚焦或不聚焦?

window.addEventListener('focus', function() {
    document.title = 'focused';
},false);

window.addEventListener('blur', function() {
    document.title = 'not focused';
},false);

To apply to your situation:要适用于您的情况:

var autopager;
function startAutopager() {
    autopager = window.setInterval(nextImage, 8000);
}
function stopAutopager() {
    window.clearInterval(autopager);
}

window.addEventListener('focus', startAutopager);    
window.addEventListener('blur', stopAutopager);

Note that in the latest version of Chromium, there is either a bug or a 'feature' which is making this less reliable, requiring that the user has clicked at least once anywhere in the window.请注意,在最新版本的 Chromium 中,有一个错误或一个“功能”会降低可靠性,要求用户至少在 window 中的任意位置单击一次。 See linked question above for details.有关详细信息,请参阅上面的链接问题。

I post an answer here: How can I make setInterval also work when a tab is inactive in Chrome?我在这里发布了一个答案: 当 Chrome 中的选项卡处于非活动状态时,如何使 setInterval 也起作用?

Just do this:只需这样做:

setInterval(function() {
    $("#your-image-container").stop(true,true);
    nextImage();

}, 1000);

inactive browser tabs buffer some of the setInterval or setTimeout functions.非活动浏览器选项卡缓冲一些 setInterval 或 setTimeout 函数。 stop(true,true) - will stop all buffered events and execute immadietly only last animation. stop(true,true) - 将停止所有缓冲事件并仅在最后一个 animation 立即执行。

The window.setTimeout() method now clamps to send no more than one timeout per second in inactive tabs. window.setTimeout() 方法现在限制在非活动选项卡中每秒发送不超过一个超时。 In addition, it now clamps nested timeouts to the smallest value allowed by the HTML5 specification: 4 ms (instead of the 10 ms it used to clamp to).此外,它现在将嵌套超时限制为 HTML5 规范所允许的最小值:4 毫秒(而不是之前的 10 毫秒)。

A few ideas comes to mind:想到了几个想法:


Idea #1想法#1

You can make it so that a short burst is idempotent .你可以使它成为一个短脉冲是幂等的。 For example, you could say:例如,你可以说:

function now() {
    return (new Date()).getTime();
}

var autopagerInterval = 8000;

function startAutopager() {
    var startImage = getCurrentImageNumber();
    var startTime = now();

    var autopager = setInterval(
        function() {
            var timeSinceStart = now() - startTime();
            var targetImage = getCurrentImageNumber + Math.ceil(timeSinceStart/autopagerInterval);
            if (getCurrentImageNumber() != targetImage)
                setImageNumber(targetImage);  // trigger animation, etc.
        },
        autopagerInterval
    );
    return autopager;
}

This way even if the function runs 1000 times, it will still run in only a few milliseconds and animate only once.这样,即使 function 运行 1000 次,它仍然只会在几毫秒内运行,并且只动画一次。

note : If the user leaves the page and comes back, it will have scrolled.注意:如果用户离开页面并返回,它将滚动。 This is probably not what the original poster wants, but I leave this solution up since it is sometimes what you want.这可能不是原始海报想要的,但我保留了这个解决方案,因为它有时是你想要的。


Idea #2想法#2

Another way to add idempotence (while still keeping your nextImage() function and not having it scroll to the bottom of the page) would be to have the function set a mutex lock which disappears after a second (cleared by another timeout).添加幂等性的另一种方法(同时仍然保持nextImage() function 并且不让它滚动到页面底部)是让 function 设置一个互斥锁,该锁在一秒钟后消失(由另一个超时清除)。 Thus even if the setInterval function was called 1000 times, only the first instance would run and the others would do nothing.因此,即使 setInterval function 被调用了 1000 次,也只有第一个实例会运行,其他实例什么也不做。

var locked = false;
var autopager = window.setInterval(function(){
    if (!locked) {
        locked = true;
        window.setTimeout(function(){
            locked=false;
        }, 1000);
        nextImage();
    }
}, 8000);

edit: this may not work, see below编辑:这可能行不通,见下文


Idea #3想法#3

I tried the following test:我尝试了以下测试:

function f() {
    console.log((new Date()) + window.focus());
    window.setTimeout(f, 1000);
}
f();

It seems to indicate that the function is being called every second.这似乎表明 function 每秒被调用一次。 This is odd... but I think this means that the callbacks are being called, but that the page renderer refuses to update the page in any graphical way while the tab is unfocused, delaying all operations until the user returns, but operations keep piling up.这很奇怪......但我认为这意味着正在调用回调,但是页面渲染器拒绝在选项卡未聚焦时以任何图形方式更新页面,延迟所有操作直到用户返回,但操作不断堆积向上。

Also the window.focus() function doesn't say if the window has focus; window.focus() function 也没有说明 window 是否有焦点; it GIVES focus to the window, and is thus irrelevant.它关注 window,因此无关紧要。

What we want is probably this: How to detect when a tab is focused or not in Chrome with Javascript?我们想要的可能是: 如何使用 Javascript 在 Chrome 中检测标签何时聚焦或不聚焦? -- you can unset your interval when the window loses focus (blur), and reset it when it gains focus. -- 您可以在 window 失去焦点(模糊)时取消设置间隔,并在获得焦点时重新设置。

I don't know exactly what is going on in your function nextImage(), but I had a similar issue.我不确切知道您的 function nextImage() 中发生了什么,但我遇到了类似的问题。 I was using animate() with setInterval() on a jQuery image slider that I created, and I was experiencing the same thing as you when I switched to a different tab and back again.我在我创建的 jQuery 图像 slider 上使用 animate() 和 setInterval(),当我切换到不同的选项卡并再次返回时,我遇到了和你一样的事情。 In my case the animate() function was being queued, so once the window regained focus the slider would go crazy.在我的情况下,animate() function 正在排队,所以一旦 window 重新获得焦点,slider 将 Z34D67BZFA11 疯狂。 To fix this I just stopped the animate() function from queuing.为了解决这个问题,我刚刚停止了 animate() function 的排队。

There are a couple ways you can do this.有几种方法可以做到这一点。 the easiest is with.stop(), but this issue and ways to fix it are documented in the jQuery docs.最简单的是 with.stop(),但是 jQuery 文档中记录了这个问题和解决方法。 Check this page near the bottom under the heading additional notes: http://api.jquery.com/animate/在标题附加注释下方的底部附近查看此页面: http://api.jquery.com/animate/

I had faced similar issue, somehow this code below works fine for me.我遇到过类似的问题,不知何故,下面的这段代码对我来说很好。

            var t1= window.setInterval('autoScroll()', 8000);

    window.addEventListener('focus', function() {
        focused = true;
        window.clearInterval(t1);
        t1 = window.setInterval('autoScroll()', 8000);
    },false);

    window.addEventListener('blur', function() {
        focused = false;
        window.clearInterval(t1);
    },false)



function autoScroll()

    {

        if ( running == true){
            if ( focused = true){
                forwardSlide();
            }


        }

        else {

            running = true;

        }



    }

Seconding the comment by jgerstle to use page visibility events instead, see https://www.w3.org/TR/page-visibility/#example-1-visibility-aware-video-playback for more around subscribing to 'visibilitychange' for hidden/visible states.借调 jgerstle 的评论以改为使用页面可见性事件,请参阅https://www.w3.org/TR/page-visibility/#example-1-visibility-aware-video-playback以了解有关订阅“visibilitychange”的更多信息隐藏/可见状态。

This seems to be more useful than focus/blur these days as it covers visible-but-not-selected windows if concerned also about multi-window operating systems.现在这似乎比 focus/blur 更有用,因为它涵盖了 visible-but-not-selected windows 如果还关注多窗口操作系统。

If you are using Soh Tanaka's image slider then just add this...to solve your Google Chrome issue:如果您使用的是 Soh Tanaka 的图像 slider 那么只需添加此...即可解决您的 Google Chrome 问题:

$(".image_reel").stop(true, true).fadeOut(300).animate({ left: -image_reelPosition}, 500 ).fadeIn(300);

Take note of the.stop() function.注意.stop() function。 Ignore the fading in and out stuff, that's what I used on my version忽略淡入淡出的东西,这就是我在我的版本中使用的

Thanks谢谢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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