setInterval在Chrome上无法正常运行

时间:2011-08-05 05:13:59

标签: javascript jquery setinterval

我有一个自定义幻灯片对象来执行名称在网站上指示的常用内容。除非我在Chrome中切换标签并返回网站标签,否则一切正常。当发生这种情况时,幻灯片会变得疯狂并开始淡化图像而忽​​略给定的setInterval间隔。找不到与此相关的任何问题,所以我想至少知道这是代码或软件问题。

这是代码(与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();

});

5 个答案:

答案 0 :(得分:11)

我倾向于使用setInterval()重复使用setTimeout() - setInterval()会出现很多问题,你不知道浏览器的繁忙程度以及间隔是否真实。

浏览器不会完全遵守您选择的超时或间隔。这主要是为了安全;防止大量事件搞乱浏览器正常运行的能力。 Chrome更适合更准确地兑现计时器,例如,当标签位于后台(see this answer)时,它仍会显着降低计时器的速度。

如果你在现有的slideshow.action()调用期间设置了一个带有setTimeout的新计时器,那么当你的浏览器无法跟上时,你就不会让事件排队,但是当它仍然很顺利时,浏览器能够这样做。

您仍然可以使用计时器ID停止计时器,该ID只会经常更改。

答案 1 :(得分:8)

Chrome(显然也是最新版本的Firefox)会在选项卡处于后台时降低setInterval的速度,以提高前景性能。当背景页面中有快速运行的定时器驱动的动画时,这可能是最重要的。当页面返回到前台时,它会“尝试”赶上并运行一堆setInterval个调用,比正常运行的速度快得多。

解决方法是:

  1. 延长setInterval的时间,以便Chrome不会乱用它(你必须查看那段时间)。
  2. 当页面进入后台时停止间隔计时器(无论如何都不需要运行幻灯片) - 然后在页面到达前台时再次启动它。
  3. 使用重复的setTimeout代替setInterval以及某种类型的重复setTimeout,如下所示:
  4. 代码:

    function nextSlide() {
        // show next slide now
        // set timer for the slide after this one
        setTimeout(function() {
            nextSlide();       // repeat
        }, xxx)
    }
    

    类似文章here

答案 2 :(得分:2)

最有可能的是,您不应期望setInterval准确无误。如果我是你,我会通过将之前的间隔时间与当前的间隔时间进行比较来检查间隔是否正确。这应该使代码更健壮。

答案 3 :(得分:0)

chrome有类似的问题

因为我已经解决了这个问题。 在开始时,记下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
}

答案 4 :(得分:0)

我发现如果间隔小于一秒,则 setInterval 不起作用。我将它设置为 500 毫秒,并在回调中调用了 xhr,但它从未被触发。使用 chromeDev for android 但不是标准版本。我将它设置为一秒(1000 毫秒)并且它运行良好。 就像 android 的 chrome 不喜欢在很小的时间间隔内做大事