Wait until setInterval() is done Wait until setInterval() is done javascript javascript

Wait until setInterval() is done


You stumbled into the pitfall most people hit at some point when they get in touch with asynchronous programming.

You cannot "wait" for an timeout/interval to finish - trying to do so would not work or block the whole page/browser. Any code that should run after the delay needs to be called from the callback you passed to setInterval when it's "done".

function rollDice(callback) {    var i = Math.floor((Math.random() * 25) + 5);    var j = i;    var test = setInterval(function() {        i--;        var value = Math.floor((Math.random() * 6) + 1);        document.getElementById("dice").src = "./images/dice/dice" + value + ".png";        if(i < 1) {            clearInterval(test);            callback(value);        }    }, 50);}

You then use it like this:

rollDice(function(value) {    // code that should run when the dice has been rolled});


You can now use Promises and async/await

Like callbacks, you can use Promises to pass a function that is called when the program is done running. If you use reject you can also handle errors with Promises.

function rollDice() {  return new Promise((resolve, reject) => {    const dice = document.getElementById('dice');    let numberOfRollsLeft = Math.floor(Math.random() * 25 + 5);    const intervalId = setInterval(() => {      const diceValue = Math.floor(Math.random() * 6 + 1);      // Display the dice's face for the new value      dice.src = `./images/dice/dice${diceValue}.png`;      // If we're done, stop rolling and return the dice's value      if (--numberOfRollsLeft < 1) {        clearInterval(intervalId);        resolve(diceValue);      }    }, 50);  });}

Then, you can use the .then() method to run a callback when the promise resolves with your diceValue.

rollDice().then((diceValue) => {  // display the dice's value to the user via the DOM})

Or, if you're in an async function, you can use the await keyword.

async function takeTurn() {  // ...  const diceValue = await rollDice()  // ...}


Orginally your code was all sequential. Here is a basic dice game where two players roll one and they see who has a bigger number. [If a tie, second person wins!]

function roleDice() {    return Math.floor(Math.random() * 6) + 1;}function game(){        var player1 = roleDice(),        player2 = roleDice(),        p1Win = player1 > player2;    alert( "Player " + (p1Win ? "1":"2") + " wins!" );}game();

The code above is really simple since it just flows. When you put in a asynchronous method like that rolling the die, you need to break up things into chunks to do processing.

function roleDice(callback) {    var i = Math.floor((Math.random() * 25) + 5);       var j = i;    var test = setInterval(function(){        i--;        var die =  Math.floor((Math.random() * 6) + 1);        document.getElementById("dice").src = "./images/dice/dice" + die + ".png";        if(i < 1) {                clearInterval(test);                callback(die);  //Return the die value back to a function to process it            }        }, 50);}function game(){    var gameInfo = {  //defaults                       "p1" : null,                       "p2" : null                   },        playerRolls = function (playerNumber) { //Start off the rolling            var callbackFnc = function(value){ //Create a callback that will                 playerFinishes(playerNumber, value);             };            roleDice( callbackFnc );        },        playerFinishes = function (playerNumber, value) { //called via the callback that role dice fires            gameInfo["p" + playerNumber] = value;            if (gameInfo.p1 !== null && gameInfo.p2 !== null ) { //checks to see if both rolls were completed, if so finish game                giveResult();            }        },        giveResult = function(){ //called when both rolls are done            var p1Win = gameInfo.p1 > gameInfo.p2;            alert( "Player " + (p1Win ? "1":"2") + " wins!" );        };                playerRolls("1");  //start player 1    playerRolls("2");  //start player 2}game();

The above code could be better in more of an OOP type of way, but it works.