0

I have a function that checks if to see if a game is over that I want to delay to give the user time to see if each answer is correct before seeing the game over screen.

The game ov er check works fine when it's run with no time out, but when I set the timeout I get the error that the function call is not a function.

setTimeout(function() {this.CheckGameOver();}, (5 * 1000)); 

Is there something wrong with the way the Timeout is being set? That's the only think could be the problem as the function works perfectly on it's own.

CheckGameOver: function() {
        // Check game over clause
        var c = this.View.children;

        if (this.players[0].answered == 13) { // Check if Player 1 won
            // Win the game
            gameStopped = true;
            isFirstQuestionSetup = true;

            if(this.PlayerCount == 1) {
                views.get('singlePlayerGame').transitionOut();
                clearInterval(this.cpu);
            } else {
                views.get('twoPlayerGame').transitionOut();
            }
            views.get('background').switchState(BACKGROUND_STATES.GAME_OVER);
            views.get('genericHud').switchState(HUD_STATES.MAIN_MENU);
            views.get('gameOver').transitionIn(this.players, this.GameType, this.Language);

        } 

        if (this.playerCount == 1) {
            if (this.cpuAnswered == 13) { // Check if CPU won
                // Lose the Game (Doh!)
                gameStopped = true;
                views.get('singlePlayerGame').transitionOut();
                clearInterval(this.cpu);
                views.get('background').switchState(BACKGROUND_STATES.GAME_OVER);
                views.get('genericHud').switchState(HUD_STATES.MAIN_MENU);
                views.get('gameOver').transitionIn(this.players, this.GameType, this.Language);
            }
        } else {
            if (this.players[0].answered == 13) { // Check if Player 2 won
                // Player 2 Wins
                gameStopped = true;
                views.get('twoPlayerGame').transitionOut();
                views.get('background').switchState(BACKGROUND_STATES.GAME_OVER);
                views.get('genericHud').switchState(HUD_STATES.MAIN_MENU);
                views.get('gameOver').transitionIn(this.players, this.GameType, this.Language);
            }
        }
    },
3
  • setTimeout(function() {this.CheckGameOver();}, 5000); Are you try with numeric value Commented Feb 1, 2017 at 10:17
  • The problem might be with this. When the timeout callback gets called, this would point to the object that generated the event (probably window). Do you see any errors in the console? Commented Feb 1, 2017 at 10:17
  • Is there anyway around using .this at all? - I'll try with a numeric value just in case Commented Feb 1, 2017 at 10:18

2 Answers 2

2

this inside the setTimeout function doesn't refer to what you think it does. You can either use an es6 arrow function

setTimeout(() => {this.CheckGameOver();}, (5 * 1000)); 

or bind this to setTimeout

setTimeout(function() {this.CheckGameOver();}.bind(this), (5 * 1000)); 
Sign up to request clarification or add additional context in comments.

5 Comments

Used .bind(this) and that fixed the issue - thanks!
The arrow function is not yet fully cross-browser as it currently only works on Firefox.
@emiliopedrollo that's not true, it also works in chrome. But you're right, all of the es6 features are not yet cross browser - that's why I added an es5 compatible version to the answer
My bad, the compatibility chart that I checked was outdated. Indeed it's largely supported now, with the usual exception of IE.
@emiliopedrollo IE is always years behind yeah... :-)
0

It happens that the anonymous function inside setTimeout is in a different closure than anything outside it thus this is something different and does not have such functions.

You should, outside setTimeout set something like

var that = this;

and inside setTimeout call for that.CheckGameOver() so it will solve your closure problem.

Alternatively, if all you have to do within a delay is to call CheckGameOver you can write your line like this:

setTimeout(this.CheckGameOver, (5 * 1000)); 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.