首页 > 解决方案 > 在函数之前使用 setTimeout 循环完成子函数

问题描述

几个晚上以来,我一直在努力解决我的代码中的时间问题,并且无法提出正确的解决方案。

伪代码说明:

//按钮上的事件监听器在每次单击时触发掷骰子

// 调用动画函数 // 生成随机值 x 次数 // 使用 setTimeout 显示每个结果 // 运行代码以确定最终的“解决”值并显示结果

HTML:

<!DOCTYPE html>

<html lang="en">
  <meta charset="utf-8">
<head>
  <title>Make Cards</title>
</head>
<body>

  <p>Total:<span id="total"></span></p>
  <div id="contain">

  <div class="die"></div>
  <div class="die"></div>
  <div class="die"></div>
  <div class="die"></div>
  <div class="die"></div>
  <div class="die"></div>

    <br>

  <button id="rollBtn">Roll</button>
  <input type="number" value = "1" min="1" max="6" id = "numDice">

  </div>

</body>
</html>

Javascript:

var diceValue = ["&#9856", "&#9857", "&#9858", "&#9859", "&#9860", 
"&#9861"];
var dice = document.querySelectorAll(".die");
// select number of dice
var numDice = document.querySelector("#numDice");
// convert string to value
var newNumDice = Number(numDice.value);
var roll = document.querySelector("#rollBtn");
var total = document.querySelector("#total");


// make animation function
// call animation function


init();

function init(){
  displayDice();
  }
//THIS IS THE BUTTON LISTERNER
roll.addEventListener("click", function(){
//THIS SHOULD RUN BEFORE THE REST OF THE FUNCTION (BUT DOESN'T SEEM TO)
  animate();
  var subTotal = 0;
  for (var i = 0; i < newNumDice; i++){
    var value = generateRandomDice() 
    dice[i].innerHTML = diceValue[value];
    subTotal = subTotal + (value+1);
    total.innerHTML = subTotal;
  }      
  for (var i = 0; i < 6; i++){
    dice[i].style.color = "black";
  }
                      })


numDice.addEventListener("click", function(){
  total.innerHTML = "-";
   newNumDice = Number(numDice.value);
  resetDice();
  displayDice();
  // console.log(Number(numDice.value));
})

function resetDice(){
  for (var i = 0; i < diceValue.length; i++){
    dice[i].innerHTML = "";
  }
}

// only display chosen number of dice

function displayDice(){
  for (var i = 0; i < newNumDice; i++){
    dice[i].innerHTML = diceValue[i];
  }
}

function generateRandomDice(){
  var dieSide = Math.floor(Math.random() * 6);
  return dieSide;
}

//ATTEMPT AT WRITING CODE FOR ANIMATION
function animate(){
  for (var i = 0; i < 50000; i++){
  var ani = setTimeout(rolling, 650);
  }
  }

function rolling(){
                for (var i = 0; i < newNumDice; i++){
    var value = generateRandomDice() 
    dice[i].innerHTML = diceValue[value];
    dice[i].style.color = "grey";
}
}

不知道发生了什么,但在我看来 animate(); 在 eventListener 的其余部分完成之前,代码不会运行。任何帮助都很棒,谢谢。

标签: javascriptsettimeout

解决方案


问题是您在执行同步代码之前正在等待异步代码完成。每次调用 setTimeout 时,它都会存储准备好调用时调用的函数(距离“现在”还有 650 毫秒!)。

要修复,您可以await让您的动画完成。以下是我如何在您的 codepen 上使用它:

更改animate为:

function animate() {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < 50000; i++) {
      setTimeout(() => {
        rolling();

        if(i == 49999)
          resolve();
      }, 650);
    }
  });
}

然后您可以通过将点击侦听器更改为此来等待 Promise 解决:

roll.addEventListener("click", async function() {
  await animate();
  var subTotal = 0;
  for (var i = 0; i < newNumDice; i++) {
    var value = generateRandomDice();
    dice[i].innerHTML = diceValue[value];
    subTotal = subTotal + (value + 1);
    total.innerHTML = subTotal;
  }
  for (var i = 0; i < 6; i++) {
    dice[i].style.color = "black";
  }
});

之后显示的结果对我来说是正确的。

希望有帮助!


推荐阅读