使用setInterval时,如果我在Chrome中切换标签并返回,则滑块会疯狂追赶

Nat*_*ert 45 javascript jquery google-chrome slider

我的网站上有一个jQuery滑块,下一张幻灯片的代码位于一个名为nextImage的函数中.我使用setInterval在计时器上运行我的函数,它完全符合我的要求:它在计时器上运行我的幻灯片.但是,如果我转到Chrome中的网站,切换到另一个标签并返回,滑块会持续穿过幻灯片,直到它"赶上".有谁知道解决这个问题的方法.以下是我的代码.

setInterval(function() {
nextImage();
}, 8000);
Run Code Online (Sandbox Code Playgroud)

nin*_*cko 40

如何使用Javascript检测Chrome中何时关注标签?

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

window.addEventListener('blur', function() {
    document.title = 'not focused';
},false);
Run Code Online (Sandbox Code Playgroud)

适用于您的情况:

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

window.addEventListener('focus', startAutopager);    
window.addEventListener('blur', stopAutopager);
Run Code Online (Sandbox Code Playgroud)

请注意,在最新版本的Chromium中,存在一个错误或"功能",这使得它不太可靠,要求用户在窗口的任何位置至少点击过一次.有关详情,请参阅上面的链接问


www*_*www 15

我在这里发布了一个答案:当Chrome中的标签处于非活动状态时,如何使setInterval也能正常工作?

这样做:

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

}, 1000);
Run Code Online (Sandbox Code Playgroud)

非活动浏览器选项卡缓冲一些setInterval或setTimeout函数.stop(true,true) - 将停止所有缓冲的事件并仅执行immadietly上一次动画.

window.setTimeout()方法现在钳制在非活动选项卡中每秒发送不超过一次超时.此外,它现在将嵌套超时限制为HTML5规范允许的最小值:4 ms(而不是用于钳位的10 ms).


nin*_*cko 6

想到一些想法:


想法#1

你可以做到这样短突发是幂等的.例如,您可以说:

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;
}
Run Code Online (Sandbox Code Playgroud)

这种方式即使该函数运行1000次,它仍将仅在几毫秒内运行并且仅动画一次.

注意:如果用户离开页面并返回,它将滚动.这可能不是原始海报想要的,但我保留了这个解决方案,因为它有时候是你想要的.


想法#2

另一种添加幂等性的方法(虽然仍然保持你的nextImage()功能而不是滚动到页面的底部)就是让函数设置一个互斥锁,它会在一秒后消失(由另一个超时清除).因此,即使setInterval函数被调用了1000次,也只会运行第一个实例而其他实例都不会执行任何操作.

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

编辑:这可能不起作用,见下文


想法#3

我尝试了以下测试:

function f() {
    console.log((new Date()) + window.focus());
    window.setTimeout(f, 1000);
}
f();
Run Code Online (Sandbox Code Playgroud)

它似乎表明该函数每秒都被调用.这很奇怪......但我认为这意味着回调被调用,但该页面渲染拒绝任何图形化的方式来更新页面,而标签是没有重点,延缓所有的操作,直到用户返回,但操作保持打桩起来.

window.focus()功能也没有说窗口是否有焦点; 它将焦点放在窗口上,因此无关紧要.

我们想要的可能是:如何使用Javascript检测Chrome中何时关注标签? - 当窗口失去焦点(模糊)时,您可以取消设置间隔,并在焦点获得焦点时重置它.