0

I'm currently building a roulette game. To the simulate wheel spinning I'm use this code:

function getColor(item){
var x = document.getElementById(item);
return x.className;
}

function spin() {
  spinning = true;
  
  for (let i = 0; i < options.length; i++) {
  document.getElementById("wheel").style.backgroundColor = getColor(options[i]);
  document.getElementById("number").innerHTML = options[i];
  
  //sleep for 100ms
  
} 
  spinning = false;
}

It does what I need but it does it too fast so you can't see every number go by. Is there a way to make the program sleep for 100ms every iteration. When I try to use setTimeout it doesn't pause the code. I've looked around at other question but they all say to use the timeout and it doesn't work for me.

Brett
  • 67
  • 8
  • Does this answer your question? [How do I add a delay in a JavaScript loop?](https://stackoverflow.com/questions/3583724/how-do-i-add-a-delay-in-a-javascript-loop) – nyjC1v2Pu8 Aug 25 '22 at 21:52

3 Answers3

1

For loops respect asynchronous calls so you make your function async and create a little sleep utility function to wait your desired ms time

function getColor(item){
  var x = document.getElementById(item);
  return x.className;
}

function sleep(time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

async function spin() {
  spinning = true;
  
  for (let i = 0; i < options.length; i++) {
    document.getElementById("wheel").style.backgroundColor = 
    getColor(options[i]);
    document.getElementById("number").innerHTML = options[i];
  
    await sleep(100)
  
  } 
  spinning = false;
}
oliverwebr
  • 459
  • 3
  • 13
1

setTimeout will actually work for you.

let spinning = false;

const options = [1, 2, 3, 4];

function getColor(item) {
  var x = document.getElementById(item);
  return x.className;
}

function spin() {
  spinning = true;
  const total = options.length;
  const delayMs = 100;
  for (let i = 0; i < total; i++) {
    setTimeout(() => {
      document.getElementById("wheel").style.backgroundColor = getColor(
        options[i]
      );
      document.getElementById("number").innerHTML = options[i];
    }, delayMs * i);
  }
  setTimeout(() => {
    spinning = false;
  }, total * delayMs);
}

spin();
<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div id="app">
      <div>
        <p id="1" class="red" />
        <p id="2" class="yellow" />
        <p id="3" class="orange" />
        <p id="4" class="blue" />
      </div>
      <div id="wheel">
        <div id="number"></div>
      </div>
    </div>

    <script src="src/index.js"></script>
  </body>
</html>
Sergey Sosunov
  • 4,124
  • 2
  • 11
  • 15
1

I can see that it's solved, I'm leaving this here anyway as an alternative way to do it using setInterval instead since I'd already written this up.

// ...
function spin() {
  spinning = true;
  // essentially simulating the for loop's functionality
  // i->options.length, but with a 100ms delay
  let i = 0;
  const interval = setInterval(() => {
    if (i < options.length) {
      ++i;
      document.getElementById('wheel').style.backgroundColor = getColor(
        options[i]
      );
      document.getElementById('number').innerHTML = options[i];
    } else {
      clearInterval(interval);
      spinning = false;
    }
  }, 100);
}
spin();
Ethicist
  • 791
  • 2
  • 7
  • 23