如何在更改选项卡(焦点)时暂停递归 setTimeout

How can I pause a recursive setTimeout while I change tab(focus)

我的代码:

  let isBlack = true;
  function animate() {
    $(".someDiv").animate({
      backgroundColor: isBlack ? "transparent" : 'black'
    }, 20);
    isBlack = !isBlack;
  }

  const delay = ms => new Promise(res => setTimeout(res, ms));
  async function animateAndWait(msArr) {
    for (let i = 0; i < msArr.length; i++) {
      animate();
      await delay(msArr[i]);
    }
  }

  flashFunction();

  async function flashFunction() {
    await animateAndWait([300, 50]);
    if (myRandomNumberBetween(1, 100) <= 10) {
      return delay(3000)
        .then(flashFunction);
    }
    await animateAndWait([300, 400]);
      delay(3000)
        .then(flashFunction);
  }

它会以大约 3 秒的间隔使 div 闪烁几次。 我的问题发生在我切换标签页时。当我在另一个选项卡上时,该浏览器会暂停计时器,然后,当我返回此选项卡时,它会(快速地)闪烁背景中错过的所有闪烁。

我想以某种方式在后台暂停计时器或清除间隔。有些人问过同样的问题,但我不能在这里包含对他们有帮助的答案。或者也许我只是不知道如何。这可能超出了我的理解范围,但如果有人有时间,我将不胜感激他们的帮助。

以下是有类似问题的人提供的一些链接:

recursive setTimeout() pause on background

Animations pause when browser tab is not visible

您可以使用 window.onblur/window.onfocus 事件来 destroy/regenerate 选项卡 loses/recovers 获得焦点时的超时。

let myTimeout;

window.onfocus = function() {
  console.log('focus')
  clearTimeout(myTimeout);
  myAction();
};

window.onblur = function(){
   console.log('blur')
   clearTimeout(myTimeout);
};

function myAction(){
  /* 
     your code ...
  */
  console.log('new cycle')
  myTimeout = setTimeout( myAction, 1000 );
}

myAction();

If you are looking for a timer capable of being paused/resumed take a look at this tiny library

如果像我这样的初学者想知道我是如何将我的代码与 colxi 对我的问题的回答结合起来的,那就是:

   let myTimeout;
   let isBlack = true;


    window.onfocus = function() {
      console.log('focus')
      clearTimeout(myTimeout);
      myAction();
    };

    window.onblur = function(){
      console.log('blur')
      clearTimeout(myTimeout);
    };

    function animate() {
      $(".playerInfoCoatTwo").animate({
        backgroundColor: isBlack ? "transparent" : 'black'
      }, 20);
      isBlack = !isBlack;
    }

    function myAction(){

      const delay = ms => new Promise(res => myTimeout = setTimeout(res, ms)); // some changes here

      async function animateAndWait(msArr) {
        for (let i = 0; i < msArr.length; i++) {
          animate();
          await delay(msArr[i]);
        }
      }

      flashFunction();

      async function flashFunction() {
        await animateAndWait([300, 50]);
        if (myRandomNumberBetween(1, 100) <= 10) {
          return delay(3000)
            .then(flashFunction);
        }
        await animateAndWait([300, 400]);
          delay(3000)
            .then(flashFunction);
      }
      console.log('new cycle') 
    }

    myAction();

但是我不知道它是否是最优的。尽管如此,它还是有效的!