简体   繁体   中英

Can I use setTimeout to visually show how a while loop runs?

I have a simple function that takes a target value (3) and generates a random number from 1 to 6 until the target is matched. I want to create a visual effect where I can see each randomly generated number on the page until the target is matched. I assign the randomly generated number to the innerHTML of ap tag each iteration, and can see this happen when I step through the function using browser dev tools. However, when I use setTimeout as shown below and run the function, no delay happens and the target value shows up immediately. Is there a way I can delay each iteration of the while loop so that I can see the randomly generated numbers on screen?

<body>
  <p id="output"></p>
  <button onclick="myFunction()">Go</button>

  <script>
    function myFunction() 
    {
      var value = 0;
      var target = 3;

      while (value != target)
      {
        value = Math.floor((Math.random() * 6) + 1);
        setTimeout(writeOutput(value), 200);
      }
    }

    function writeOutput(value)
    {
      document.getElementById("output").innerHTML = value;
    }
  </script>
</body>

Using async / await makes this pretty easy. When you use await inside a while-loop, the loop pauses until the promise resolves.

Here, I've created a sleep function that returns a promise that resolves after the given number of milliseconds. The loop will pause for that many milliseconds before resuming.

Introduction for async / await here: https://javascript.info/async-await

 async function myFunction() { var value = 0; var target = 3; while (value != target) { value = Math.floor((Math.random() * 6) + 1); writeOutput(value) await sleep(500) } } function writeOutput(value) { document.getElementById("output").innerHTML = value; } function sleep(ms) { return new Promise((resolve) => { setTimeout(resolve, ms) }) }
 <p id="output"></p> <button onclick="myFunction()">Go</button>

setTimeout returns immediately so it should be call from inside a parent setTimeout . Something like this.

 function myFunction() { var target = 3; var out = document.getElementById("output"); function checkResult() { var value = Math.floor((Math.random() * 6) + 1); writeOutput(value); if (value !== target) setTimeout(checkResult, 200); } function writeOutput(value) { out.innerHTML = value; } setTimeout(checkResult, 200); }
 <p id="output"></p> <button onclick="myFunction()">Go</button>

The easiest way to do this would probably be... not to do it in a loop, but just check the value once, and arm the timeout to do the entire function again if unsuccessful. Guess this kinda defies your purpose, though. And yea, apparently, nowdays you CAN do a sleep in JS, see here - What is the JavaScript version of sleep()?

 function writeOutput(value) { document.getElementById("output").innerHTML = value; } function myFunction() { var value = Math.floor((Math.random() * 6) + 1); var target = 3; writeOutput(value); if (value != target) setTimeout(myFunction, 200); }
 <p id="output"></p> <button onclick="myFunction()">Go</button>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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