简体   繁体   English

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

[英]setInterval() acts weird after switching tabs

I have created an effect using javascript to show top categories in my project. 我使用javascript创建了一种效果,以显示项目中的顶级类别。

在此处输入图片说明

As you can see in the image above, it works perfectly fine. 正如您在上图中所看到的,它工作得很好。 But after running for sometime; 但是跑了一段时间后 If the user leaves this page and switched to another tab and come back to this after sometime, then it starts to act weird. 如果用户离开此页面并切换到另一个选项卡,并在一段时间后返回到该选项卡,则它开始表现得很奇怪。

在此处输入图片说明

Below is the code which I'm using to make this effect. 下面是我用来实现这种效果的代码。

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

What is causing this problem? 是什么导致此问题? What am I missing? 我想念什么?

Timers get throttled back when the tab doesn't have focus (and many other odd games, such as being accelerated when focus returns), so your setInterval and your setTimeout may get out of sync. 当选项卡没有焦点时(以及许多其他奇怪的游戏,例如焦点返回时加速),计时器就会受到限制,因此setIntervalsetTimeout可能会不同步。

Instead, just use setTimeout , where each action (fade out and fade in) triggers the next: 而是使用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);
}

And/or you might consider the callbacks that fadeOut and fadeIn can trigger, in particular on the fadeOut : 和/或您可能考虑了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);
}

Side note: If you like, you can replace 旁注:如果您愿意,可以更换

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

with

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

The 3000ms interval might run faster than a 400ms timeout as the browser tries to get the interval in sync after you get back to the tab. 回到顶端选项卡后,浏览器将尝试使间隔同步,因此3000ms间隔的运行时间可能比400ms超时快。 To resolve this, you could use a delayed loop, eg: 要解决此问题,您可以使用延迟循环,例如:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM