首页 > 解决方案 > 不规则间隔的嵌套 settimeout(更复杂的方式)

问题描述

我得到了这个递归函数,里面有嵌套的 settimeout 函数。间隔应该是这样的。它们不是线性的(希望这是我需要的词,英语不是我的母语)。我什至想在这里添加更多的 settimeout 函数。我见过的解决此类问题的链接用于线性进展,例如时钟倒计时等。但我有一些不规则的间隔模式。那么有没有更好,更复杂的方法来做到这一点......这是我的代码:

  function betterBlitzColor() {

  $(".playerInfoCoatTwo").animate({ backgroundColor: "transparent" }, 20);
  setTimeout(function () {
    $(".playerInfoCoatTwo").animate({ backgroundColor: "black" }, 20)
    setTimeout(function () {
      $(".playerInfoCoatTwo").animate({ backgroundColor: "transparent" }, 20)
        setTimeout(function () {
          $(".playerInfoCoatTwo").animate({ backgroundColor: "black" }, 20)
          setTimeout(function () {
            $(".playerInfoCoatTwo").animate({ backgroundColor: "transparent" }, 20)
            setTimeout(function () {
              $(".playerInfoCoatTwo").animate({ backgroundColor: "black" }, 20)
              if(myRandomNumberBetween(1, 100) > 10)
              {
                setTimeout(function () {
                  $(".playerInfoCoatTwo").animate({ backgroundColor: "transparent" }, 20)
                  setTimeout(function () {
                    $(".playerInfoCoatTwo").animate({ backgroundColor: "black" }, 20)
                    if(myRandomNumberBetween(1, 100) > 10)
                    {
                      setTimeout(function () {
                        $(".playerInfoCoatTwo").animate({ backgroundColor: "transparent" }, 20)
                        setTimeout(function () {
                          $(".playerInfoCoatTwo").animate({ backgroundColor: "black" }, 20)
                            setTimeout(function () {
                              $(".playerInfoCoatTwo").animate({ backgroundColor: "transparent" }, 20)
                              setTimeout(function () {
                                $(".playerInfoCoatTwo").animate({ backgroundColor: "black" }, 20)
                                setTimeout(betterBlitzColor, myRandomNumberBetween(5000, 5000));   // inside 
                              }, 150)
                            }, 100)
                        }, 100)
                    }, 400) // level 3

                    }
                    else{
                      setTimeout(betterBlitzColor, myRandomNumberBetween(5000, 5000));   // inside 
                    }
                  }, 300)
              }, 650) // level 2

              }
              else{

                setTimeout(betterBlitzColor, myRandomNumberBetween(5000, 5000));   // inside 
              }
            }, 50)
          }, 50)
        }, 150)
    }, 50)
  }, 300)

  }

我只能说这段代码看起来很奇怪。必须有一些更好的方法......我访问过的链接更像是这样解决问题:

嵌套的 setTimeout 替代方案?

我不知道在我的情况下我将如何使用它。一些帮助或建议?

标签: javascriptsetinterval

解决方案


因为您的animate调用总是针对同一个元素,并且集合backgroundColor是可预测的(从透明到黑色到透明等等),所以所有这些功能都可以抽象为一个函数。为了轻松链接它,您可以让该函数返回 aPromise在所需时间后解析,允许您使用.thens 或await不使用回调嵌套。此外,由于您经常连续执行许多动画(延迟后),您可以传递一个数组,其中包含每个动画之间要等待的毫秒数,并使用循环进行动画处理,然后awaitPromise那么多毫秒后解析。

当您在长代码块和短代码块之间交替时,可以减少缩进地狱的其他方法是提前返回。也就是说,与您的if (myRandomNumberBetween(1, 100) > 10) {测试一样,而不是

if (test1) {
  // many lines 1
  if (test2) {
    // many lines 2

    // many more lines
  } else {
    // do something else 1
} else {
  // do something else 2
}

这很不可读 - 每个测试都do something else连接到哪个测试?这不是立即显而易见的,这是一个问题。相反,您可以执行以下操作:

if (!test) {
  // do something else 1
  return;
}
// many lines 1
if (!test2) {
  // do something else 2
  return;
}
// many lines 2

将所有这些转换为原始代码的修复:

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

// Delay function,
// allows for much flatter code when you can `await` a `Promise` compared to `setTimeout`:
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]);
  }
}

async function betterBlitzColor() {
  await animateAndWait([0, 300, 50, 150, 50, 50]);
  if (myRandomNumberBetween(1, 100) <= 10) {
    return delay(myRandomNumberBetween(9000, 18000))
      .then(betterBlitzColor);
  }
  await animateAndWait([650, 300]);
  if (myRandomNumberBetween(1, 100) <= 10) {
    return delay(myRandomNumberBetween(9000, 18000))
      .then(betterBlitzColor);
  }
  await animateAndWait([400, 100, 100, 150]);
  delay(myRandomNumberBetween(9000, 18000))
    .then(betterBlitzColor);
}

推荐阅读