setInterval()在切换制表符后表现怪异

时间:2018-10-23 13:52:01

标签: javascript jquery setinterval effects

我已经使用javascript创建了一种效果,以显示项目中的顶级类别。

enter image description here

如上图所示,它工作得很好。但是跑了一段时间后如果用户离开此页面并切换到另一个选项卡,并在一段时间后返回到该选项卡,则它开始变得很奇怪。

enter image description here

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

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();
});

是什么导致此问题?我想念什么?

2 个答案:

答案 0 :(得分:6)

当选项卡没有焦点时(以及许多其他奇数游戏,例如焦点返回时加速),计时器会受到限制,因此您的setIntervalsetTimeout可能会不同步

相反,只需使用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);
}

和/或您可能会考虑fadeOutfadeIn可以触发的回调,尤其是在fadeOut上:

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;
}

使用

curCat = (curCat + 1) % cats.length;

答案 1 :(得分:0)

3000ms间隔的运行时间可能比400ms超时快,因为在您返回到标签页后,浏览器会尝试使间隔同步。要解决此问题,您可以使用延迟循环,例如:

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

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