Martijn
Martijn

Reputation: 383

Breaking out of setTimeout loop

I'm having some trouble breaking out of a setTimeout loop.

for (var i = 0; i < 75; i++) {
  setTimeout(function (i) {
    return function () {
      console.log("turn no. " + i);
      if (table.game.playerWon) {
        console.log('Player won');
        // I want to stop the loop now
        // i = 75; didn't work
      }
    };
  }(i), 100 * i);
}

I've read like 100 setTimeout related posts, but can't figure this one out.

edit:

Let me clarify a bit when I'm trying to accomplish.

My game has 75 turns, each turn should take about 500ms, during that turn I want to check if a condition is met and announce that the player won, after the player has won there is no need to continue the rest of the turns.

Upvotes: 20

Views: 40344

Answers (4)

Ilan Frumer
Ilan Frumer

Reputation: 32357

You shouldn't use a for loop , just a recursive setTimeout

setInterval does not fit for so many things:

  • If an error occurs you cannot stop the train.
  • If you need different execution time steps.
  • If you need to pass data inside the chain.
  • If you need to do something asynchronous.
  • And the worse thing - SETINTERVAL DOES NOT GUARANTEE EXECUTION
  • So use it only if you know what you are doing!

Solution:

var func = function(i){

    return function(){
        if (i >= 75) return;
        console.log("turn no. " + i);

        if(table.game.playerWon) {
            console.log('Player won');
        } else {
            setTimeout(func(++i), 500); 
        }

    }   
}

setTimeout(func(0), 500); 

You can run it in node.js if you want to check how it works:

var winTurn = 10;

var func = function(i){

    return function(){
        if (i >= 75) return;
        console.log("turn no. " + i);

        if(i === winTurn) {
            console.log('Player won');
        } else {
            setTimeout(func(++i), 50); 
        }

    }   
}

setTimeout(func(1), 50); 

Upvotes: 13

php-dev
php-dev

Reputation: 7156

Here is an example of what you should write

var timeouts = [];
for (var i = 0; i < 75; i++) {

    timeouts[i] = setTimeout(function(i) {

        return function() {

            console.log("turn no. " + i);

            if(table.game.playerWon) {
                console.log('Player won');
                // I want to stop the loop now
                for(var k = i; k < timeouts.length; k++) {
                    clearTimeout(timeouts[i]);
                }
            }

        };

    }(i), 100*i);

}

Another simpler workaround is a call only setTimeout when table.game.playerWon is false.

var timeoutFunction = function(i) {

    return function() {

        console.log("turn no. " + i);

        if(table.game.playerWon) {
            console.log('Player won');
            // Game stopped
        } else {
            timeout = setTimeout(timeoutFunction(i+1), 100);  
        }
    };

}

var timeout = setTimeout(timeoutFunction(0), 100);

Hope it helps

Upvotes: 0

Santiago Rebella
Santiago Rebella

Reputation: 2449

I think would be better you use a setInterval instead of setTimeout.

And for clear both of them you assign them to a variable and then you clear the timeout with

var myVar = setTimeout(func, time);
var myVar2 = setInterval(func, time);

clearTimeout(myVar);
clearInterval(myVar2);

Upvotes: 5

Joseph Silber
Joseph Silber

Reputation: 219920

Instead of setting all those timers, create one continuous timer with setInterval:

var counter = 0;

var timer = setInterval(function () {

    console.log("turn no. " + counter);

    if (table.game.playerWon) {
        console.log('Player won');
    }

    if (counter >= 75 || table.game.playerWon) {
        clearInterval(timer);
    }

    counter++;

}, 100);

If your turns should take 500ms, change that last 100 to 500.

Upvotes: 25

Related Questions