setInterval 在 Chrome 上无法正常工作

IT技术 javascript jquery setinterval
2021-02-20 09:36:28

我有一个定制的幻灯片对象来执行名称在网站上指示的常用内容。一切都很好,除非我在 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个回答

我更喜欢重复使用 setTimeout() 而不是使用 setInterval() - setInterval() 可能会出现很多问题,而且您不知道浏览器有多忙以及间隔是否现实。

浏览器不会完全遵守您选择的超时或间隔。这主要是为了安全;以防止大量事件干扰浏览器正常运行的能力。例如,当标签在后台(参见此答案)时,Chrome更准确地更准确地尊重计时器,尽管它仍然显着慢下来(参见此答案)。

如果您在现有的对 slideshow.action() 的调用期间使用 setTimeout 设置了一个新计时器,那么当您的浏览器跟不上时,您将不会出现事件排队,但是当浏览器处于能够这样做。

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

尝试setTimeout()没有任何成功。即使我告诉脚本改变时间戳并调整间隔(使用console.log我可以看到它从未改变,这让我相信 Chrome 冻结了标签进程或其他东西),Chrome 标签的问题仍然会发生
2021-04-26 09:36:28
2021-05-17 09:36:28

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

解决方法是:

  1. 延长时间,setInterval这样 Chrome 就不会弄乱它(你必须查一下那个时间是多少)。
  2. 当页面进入后台时停止你的间隔计时器(当它不可见时不需要运行幻灯片) - 然后当页面进入前台时再次启动它。
  3. 使用重复setTimeout而不是setInterval某种类型的重复 setTimeout 像这样:

代码:

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

类似的帖子在这里

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

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
}
setInterval(process(), ...)将尝试执行 的返回值process,这几乎肯定不是您想要的。setInterval将函数引用作为其第一个参数(或字符串,但在这里并不重要)。
2021-05-04 09:36:28

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