Javascript 使用 setInterval 时,如果我在 Chrome 中切换标签页并返回,滑块会疯狂追赶
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6183463/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When using setInterval, if I switch tabs in Chrome and go back, the slider goes crazy catching up
提问by Nathan Shubert
I have a jQuery slider on my site and the code going to the next slide is in a function called nextImage. I used setInterval to run my function on a timer, and it does exactly what I want: it runs my slides on a timer. 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'. Does anyone know of a way to fix this. The following is my code.
我的网站上有一个 jQuery 滑块,下一张幻灯片的代码位于名为 nextImage 的函数中。我使用 setInterval 在计时器上运行我的函数,它完全符合我的要求:它在计时器上运行我的幻灯片。但是,如果我在 Chrome 中访问该站点,切换到另一个选项卡并返回,滑块会连续运行幻灯片,直到它“赶上”。有谁知道解决这个问题的方法。以下是我的代码。
setInterval(function() {
nextImage();
}, 8000);
回答by ninjagecko
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. See linked question above for details.
请注意,在最新版本的 Chromium 中,存在一个错误或“功能”使其不太可靠,要求用户至少在窗口中的任何地方单击一次。有关详细信息,请参阅上面的链接问题。
回答by www
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. stop(true,true) - will stop all buffered events and execute immadietly only last animation.
非活动浏览器选项卡会缓冲一些 setInterval 或 setTimeout 函数。stop(true,true) - 将停止所有缓冲事件并仅立即执行最后一个动画。
The window.setTimeout() method now clamps to send no more than one timeout per second in inactive tabs. 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).
window.setTimeout() 方法现在限制为在非活动选项卡中每秒发送不超过一个超时。此外,它现在将嵌套超时限制为 HTML5 规范允许的最小值:4 毫秒(而不是它过去用于限制的 10 毫秒)。
回答by ninjagecko
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.
这样即使函数运行了 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). Thus even if the setInterval function was called 1000 times, only the first instance would run and the others would do nothing.
添加幂等性的另一种方法(同时仍然保持您的nextImage()
函数并且不让它滚动到页面底部)是让函数设置一个互斥锁,该锁在一秒钟后消失(由另一个超时清除)。因此,即使 setInterval 函数被调用 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. This is odd... but I think this means that the callbacks arebeing called, but that the page rendererrefuses 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; it GIVES focus to the window, and is thus irrelevant.
该window.focus()
函数也不会说明窗口是否具有焦点;它将焦点放在窗口上,因此无关紧要。
What we want is probably this: How to detect when a tab is focused or not in Chrome with Javascript?-- you can unset your interval when the window loses focus (blur), and reset it when it gains focus.
我们想要的可能是这样的:如何使用 Javascript 检测 Chrome 中的选项卡何时聚焦或不聚焦?-- 您可以在窗口失去焦点(模糊)时取消设置间隔,并在获得焦点时重置间隔。
回答by 000justin000
I don't know exactly what is going on in your function nextImage(), but I had a similar issue. 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. In my case the animate() function was being queued, so once the window regained focus the slider would go crazy. To fix this I just stopped the animate() function from queuing.
我不知道你的函数 nextImage() 到底发生了什么,但我遇到了类似的问题。我在我创建的 jQuery 图像滑块上使用 animate() 和 setInterval(),当我切换到不同的选项卡并再次返回时,我遇到了与您相同的事情。在我的例子中 animate() 函数正在排队,所以一旦窗口重新获得焦点,滑块就会发疯。为了解决这个问题,我只是停止了 animate() 函数的排队。
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. Check this page near the bottom under the heading additional notes: http://api.jquery.com/animate/
有几种方法可以做到这一点。最简单的方法是使用 .stop(),但是这个问题和修复方法记录在 jQuery 文档中。在标题附加说明下检查底部附近的此页面:http: //api.jquery.com/animate/
回答by Nasir
If you are using Soh Tanaka's image slider then just add this...to solve your Google Chrome issue:
如果您使用的是 Soh Tanaka 的图像滑块,那么只需添加此...即可解决您的 Google Chrome 问题:
$(".image_reel").stop(true, true).fadeOut(300).animate({ left: -image_reelPosition}, 500 ).fadeIn(300);
$(".image_reel").stop(true, true).fadeOut(300).animate({ left: -image_reelPosition}, 500 ).fadeIn(300);
Take note of the .stop() function. Ignore the fading in and out stuff, that's what I used on my version
注意 .stop() 函数。忽略淡入淡出的东西,这就是我在我的版本中使用的
Thanks
谢谢
回答by Maheshchandra Hegde
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;
}
}