Javascript setInterval()在切换制表符后行为怪异

Javascript setInterval()在切换制表符后行为怪异,javascript,jquery,setinterval,effects,Javascript,Jquery,Setinterval,Effects,我已经使用javascript创建了一个效果来显示项目中的顶级类别 正如您在上图中所看到的,它工作得非常好。但是跑了一段时间之后,;如果用户离开这个页面,切换到另一个标签页,过了一段时间又回到这个页面,那么它就会开始表现出奇怪的行为 下面是我用来实现这个效果的代码 var curCat = 0; var cats = [ "<a href='/search/?cat=1'>Animals</a>", "<a href='/search/?cat=2'&g

我已经使用javascript创建了一个效果来显示项目中的顶级类别

正如您在上图中所看到的,它工作得非常好。但是跑了一段时间之后,;如果用户离开这个页面,切换到另一个标签页,过了一段时间又回到这个页面,那么它就会开始表现出奇怪的行为

下面是我用来实现这个效果的代码

var curCat = 0;
var cats = [
  "<a href='/search/?cat=1'>Animals</a>",
  "<a href='/search/?cat=2'>Graffiti</a>",
  "<a href='/search/?cat=3'>Figures</a>",
  "<a href='/search/?cat=6'>Landscape</a>",
  "<a href='/search/?cat=7'>Portrait</a>",
  "<a href='/search/?cat=9'>Other</a>"
];

function catSlider() {
  $(catDisplay).html(cats[curCat]);
  $(catDisplay).fadeIn();
  setInterval(function() {
    $(catDisplay).fadeOut();
    setTimeout(function() {
      if (++curCat >= cats.length) {
        curCat = 0;
      }
      $(catDisplay).html(cats[curCat]);
      $(catDisplay).fadeIn();
    }, 400);
  }, 3000);
}

$(document).ready(function() {
  catSlider();
});
var curCat=0;
变量猫=[
"",
"",
"",
"",
"",
""
];
函数catSlider(){
$(catDisplay.html(cats[curCat]);
$(catDisplay.fadeIn();
setInterval(函数(){
$(catDisplay).fadeOut();
setTimeout(函数(){
如果(++curCat>=猫的长度){
curCat=0;
}
$(catDisplay.html(cats[curCat]);
$(catDisplay.fadeIn();
}, 400);
}, 3000);
}
$(文档).ready(函数(){
catSlider();
});

是什么导致了这个问题?我错过了什么?

当选项卡没有焦点时计时器会被限制(以及许多其他奇怪的游戏,例如当焦点返回时会被加速),因此您的
设置间隔
设置超时
可能会不同步

相反,只需使用
setTimeout
,其中每个操作(淡出和淡入)都会触发下一个操作:

function catSlider() {
  $(catDisplay).html(cats[curCat]);
  $(catDisplay).fadeIn();
  function fadeOut() {
    $(catDisplay).fadeOut();
    setTimeout(fadeIn, 400);
  }
  function fadeIn() {
    if (++curCat >= cats.length) {
      curCat = 0;
    }
    $(catDisplay).html(cats[curCat]);
    $(catDisplay).fadeIn();
    setTimeout(fadeOut, 3000);
  }
  setTimeout(fadeOut, 3000);
}

和/或您可以考虑“代码> FADEOUT 和<代码> FADEIN < /代码>的回调可以触发,特别是在<代码> FAUDOUT < /代码>:

function catSlider() {
  $(catDisplay).html(cats[curCat]);
  $(catDisplay).fadeIn();
  function fadeOut() {
    $(catDisplay).fadeOut(fadeIn);  // ***
  }
  function fadeIn() {
    if (++curCat >= cats.length) {
      curCat = 0;
    }
    $(catDisplay).html(cats[curCat]);
    $(catDisplay).fadeIn();
    setTimeout(fadeOut, 3000);
  }
  setTimeout(fadeOut, 3000);
}

旁注:如果您愿意,您可以更换

if (++curCat >= cats.length) {
  curCat = 0;
}


返回选项卡后,浏览器尝试同步3000ms的间隔,因此3000ms的间隔可能比400ms的超时快。要解决此问题,可以使用延迟循环,例如:

 const timer = ms => new Promise(res => setTimeout(res, ms));

 (async function() {
    while(true) {
      hideCurrent();
      await timer(400);
      showNext();
      await timer(2600);
   }
 })()

这是因为您在间隔中有一个超时。@JᴀʏMᴇᴇ 我需要超时来保持两个显示项之间的间隔stimeout+interval=为什么?@epascarello-对我来说很有意义。每三秒淡出,0.4秒后淡入;冲洗,重复。如果不是为了节流,就可以了。超时时的400与
fadeOut()
的默认动画时间相匹配-因此它是fadeOut,完成后,设置值并淡入-这就是淡出回调的目的。非常感谢。从来不知道会有节流问题。@RoshanaPitigala-浏览器在过去几年才真正开始显著地做这件事。:-)我认为在那之前有一个完全暂停计时器,但不是他们现在的复杂行为。
 const timer = ms => new Promise(res => setTimeout(res, ms));

 (async function() {
    while(true) {
      hideCurrent();
      await timer(400);
      showNext();
      await timer(2600);
   }
 })()