Javascript setInterval 在 Chrome 上无法正常工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6951727/
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
setInterval not working properly on Chrome
提问by yoda
I have a custom made slideshow object to perform the usual stuff the name indicates on a website. It all works well except when I switch tabs in Chrome and come back to the website tab. When that happens, the slideshow goes nuts and starts fading the images disregarding the setInterval
interval given. Can't find anyhing related to this, so I'd like to at least know if it's a problem with the code or a software issue.
我有一个定制的幻灯片对象来执行名称在网站上指示的常用内容。一切都很好,除非我在 Chrome 中切换标签并返回网站标签。当这种情况发生时,幻灯片会变得疯狂并开始淡化图像,而不管setInterval
给定的间隔。找不到与此相关的任何内容,所以我想至少知道这是代码问题还是软件问题。
Here's the code (being used with jQuery) :
这是代码(与 jQuery 一起使用):
$(function() {
// slideshow
var slideshow = {
id : false,
current : 0,
count : 0,
interval : false,
init : function(data) {
if (!data)
return false;
$.each(data, $.proxy(
function(index, value) {
this[index] = data[index];
}, this)
);
this.count = this.images.length;
for (x=1;x<=this.count;x++)
$('#slider ul.nav').append('<li></li>');
$('#slider ul.nav li').live('click', function()
{
slideshow.click(this);
});
$('#slider ul.nav li:eq(0)').addClass('on');
$('#slider ul.nav').css('width', (15*this.count)+'px');
return true;
},
start : function () {
slideshow.id = setInterval(function() { slideshow.action(); }, slideshow.options.interval);
},
stop : function() {
clearInterval(slideshow.id);
},
action : function() {
slideshow.current < (slideshow.count-1) ? slideshow.current++ : slideshow.current = 0;
$('#slider img').fadeOut('normal', function() {
$('#slider img').attr('src', slideshow.images[slideshow.current].url);
$('#slider ul.nav li').removeClass('on');
$('#slider ul.nav li:eq('+slideshow.current+')').addClass('on');
$('#slider div.title').html(slideshow.images[slideshow.current].title);
$('#slider div.description').html(slideshow.images[slideshow.current].description);
$('#slider a.more').attr('href', slideshow.images[slideshow.current].target);
}).fadeIn('normal');
return true;
},
click : function(o) {
slideshow.stop();
var index = $('#slider ul.nav li').index(o);
slideshow.current = index;
$('#slider img').fadeOut('normal', function() {
$('#slider img').attr('src', slideshow.images[index].url);
$('#slider ul.nav li').removeClass('on');
$(o).addClass('on');
$('#slider div.title').html(slideshow.images[index].title);
$('#slider div.description').html(slideshow.images[index].description);
$('#slider a.more').attr('href', slideshow.images[index].target);
}).fadeIn('normal');
slideshow.start();
return true;
},
};
slideshow.init(slider);
slideshow.start();
});
回答by thomasrutter
I'd favour using setTimeout() repeatedly over using setInterval() - so many things can go wrong with setInterval() and you don't know how busy the browser is and whether the interval is realistic.
我更喜欢重复使用 setTimeout() 而不是使用 setInterval() - setInterval() 可能会出现很多问题,而且您不知道浏览器有多忙以及间隔是否现实。
Browsers don't honour your chosen timeout or interval exactly. This is mainly for security; to prevent a flood of events from messing with the browser's ability to function normally. Chrome is better about honouring timers more accurately, though it does still slow them down significantly when a tab is in the background (see this answer), for example.
浏览器不会完全遵守您选择的超时或间隔。这主要是为了安全;以防止大量事件干扰浏览器正常运行的能力。例如,当标签在后台(参见此答案)时,Chrome更准确地更准确地尊重计时器,尽管它仍然可以显着慢下来。
If you set a new timer with setTimeout during your existing call to slideshow.action(), then you won't get events queuing up when your browser can't quite keep up, but it will still go nice and quickly when the browser is able to do so.
如果您在现有的对 slideshow.action() 的调用期间使用 setTimeout 设置了一个新计时器,那么当您的浏览器跟不上时,您将不会出现事件排队,但是当浏览器处于能够这样做。
You will still be able to stop the timer using the timer ID, that ID will just change often.
您仍然可以使用计时器 ID 停止计时器,该 ID 只会经常更改。
回答by jfriend00
Chrome (and apparently the latest versions of Firefox too) reduce the speed of setInterval
when the tab is in the background to improve foreground performance. This probably matters the most when there are fast running timer-driven animations in background pages. When the page comes back to the foreground, it "tries" to catch up and runs a bunch of setInterval
calls much faster than they would normally run.
Chrome(显然也是最新版本的 Firefox)会降低setInterval
标签在后台时的速度以提高前台性能。当后台页面中有快速运行的计时器驱动动画时,这可能最重要。当页面返回到前台时,它“尝试”赶上并以setInterval
比通常运行速度快得多的速度运行一堆调用。
The work-arounds are:
解决方法是:
- Lengthen the time of the
setInterval
so Chrome won't mess with it (you'd have to look up what that time is). - Stop your interval timer when the page goes in the background (no need to run slides when it's not visible anyway) - then start it up again when the page comes to the foreground.
- Use repeated
setTimeout
instead ofsetInterval
with some type of repeated setTimeout like this:
- 延长时间,
setInterval
这样 Chrome 就不会弄乱它(你必须查一下那个时间是多少)。 - 当页面进入后台时停止你的间隔计时器(当它不可见时不需要运行幻灯片) - 然后当页面进入前台时再次启动它。
- 使用重复
setTimeout
而不是setInterval
某种类型的重复 setTimeout 像这样:
Code:
代码:
function nextSlide() {
// show next slide now
// set timer for the slide after this one
setTimeout(function() {
nextSlide(); // repeat
}, xxx)
}
Similar post here.
类似的帖子在这里。
回答by laurent
Most likely, you shouldn't expect setInterval to ever be accurate. If I were you, I would check that the interval is correct by comparing the previous interval time to the current one. That should make the code more robust.
很可能,您不应该期望 setInterval 永远准确。如果我是你,我会通过将前一个间隔时间与当前间隔时间进行比较来检查间隔是否正确。这应该使代码更健壮。
回答by A. Krepchuk
There was a similar problem with chrome
chrome 也有类似的问题
As I have solved this problem. At the start, write down mktime variable, and then simply subtracted from the current time. Example:
因为我已经解决了这个问题。在开始时,记下 mktime 变量,然后简单地从当前时间中减去。例子:
var values = {};
function mktime(){
var date = new Date();
return Math.floor(date.getTime()/1000);
}
function getTime(string){
var splitContent = string.split(/\:/g);
var hours = parseInt(splitContent[0]) * 60 * 60;
var minutes = parseInt(splitContent[1]) * 60;
var seconds = parseInt(splitContent[2]);
return hours + minutes + seconds;
}
function startTimer(time){
values.startMkTime = mktime();
values.startTime = getTime(time);
setInterval(process(),1000);
}
function process(){
values.currentTime = (mktime() - values.startMkTime) + o.values.startTime;//new code
}