0

I am really disappointed in Stack overflow. I had read the post which this is supposed to be a duplicate of several times and it did not help which is why I posted this one explaining why it was different, but STILL got marked as duplicate. Also, the way the callbacks are called in that alleged duplicate are different, and I could not apply them to the way I call my callbacks as I am not a rocket scientist or know the inner workings of javascript (although I have read 3 javascript books from cover to cover). I do have an answer now, and want to post the solution, but cant. So everyone in my situation, can't benefit from a documented solution which is different syntax from the duplicate.

I know there are lots of posts about this in javascript functions and objects, but there seems to be no similar help for javascript classes. classes are different because you cant use the "var self=this" trick to solve the problem. Solutions to not being able to get at class data include:

  1. bind. I have not been able to get this to work through the many levels of indirection required to make the program manageable. I cant find any examples of bind in callbacks without self (which doesnt work in classes) or the underscore library.
  2. arrow functions. these are fine if your entire logic is one line, but all mine are much larger and some need to be called from several places, so these are not an option I assume.
  3. var self = this. As mentioned this does not work in javacript classes.

Here is some code:

class Game{
      constructor(minPlayers) {
         this.minPlayers = minPlayers
         this.players=[]
         this.waitTimer=null
      } // constructor

      addPlayer(player) {
          this.players.plush(player)
          // if we are the first player, set a timeout waiting for others.
          if (this.players.length ==1) {
             this.waitTimer= setTimeout(this.waitForPlayers, 5000)
          } else {
             // stuff
          }
      } // addPlayer

      // this function is too long to be an arrow function.
      waitForPlayers() {
         if (this.players.length < this.minPlayers) { // error this.xx undefined.
              // do stuff
              this.notifyAllPlayers("Game Aborted, not enough players")  
         } // else ....
      }

      notifyAllPlayers(message){
         for (let i=0; i<this.players.length; i++) {  // error this.players undefined
            console.log(this.players[i].name) // error this.players undefined
         }
      }

} // Game

This is called by something like this:

let Game = require('./game')
let game= new Game(4)
game.addPlayer(bob)

The crux is how to get "this" from a function called by a callback called by a function? Where do all the binds go?

I have tried things like this:

this.waitTimer= setTimeout(this.waitForPlayers, 5000).bind(this)

and

waitForPlayers() {
     // stuff
}.bind(this)

but these dont work.

== SOLUTION ==

sadly, I cant add this as an actual solution because the question has been incorrectly marked as a duplcate. Here is the solution:

 this.waitTimer= setTimeout(this.waitForPlayers.bind(this), 5000)

This is how it was done in the "not a" duplicate:

transport.on('data', ( function () {
     alert(this.data);
 }).bind(this) );

Which I had read several times but didnt know how to apply to my case because it is not the same. I have no idea what transport.on is even. It might look the same to a rocket scientist, but stack overflow is also here to help non rocket scientists, or at least used to be.

John Little
  • 10,707
  • 19
  • 86
  • 158
  • It works exactly the same way in classes as it would without them. – Bergi Mar 18 '17 at 22:31
  • 1
    You were looking for `this.waitTimer= setTimeout(this.waitForPlayers.bind(this), 5000)` - you need to bind the passed method, not the return value of the call. – Bergi Mar 18 '17 at 22:32
  • Arrow functions have no line limit? And still, you can always use a one-line arrow function that calls your large method. – Bergi Mar 18 '17 at 22:33
  • you also need `this` in from of your method calls: `this.notifyAllPlayers` – Zevan Mar 18 '17 at 22:34
  • Here is a working codepen http://codepen.io/ZevanRosser/pen/GWyyEy?editors=0011 – Zevan Mar 18 '17 at 22:34
  • @bergi, this is NOT the same with classes as without them, as with classes, you can NOT use the var stelf = this to solve the problem unfortuatnely. – John Little Mar 18 '17 at 22:44
  • @bergi, putting say 30 lines of code inside several arrow functions will make the encolsing function huge and unmanageable. – John Little Mar 18 '17 at 22:45
  • @bergi, how would you use a function inside an arrow function? I assume also that this would defeat the object of having arrow functions as you can use say "console.log(this.xx)" in side an arrow function and have this work correctly. I fou did say "call some function()" inside an arrow function, you would be back to square one in trying to get the right "this" – John Little Mar 18 '17 at 22:47
  • It *is* a duplicate. *"didnt know how to apply to my case because it is not the same"* `function () { alert(this.data);})` and `this.waitForPlayers` are both functions. Functions have a `.bind` method that you can call. Of course the duplicate won't use the exact same variable names and values as you do. *"I have no idea what transport.on is even"* It's defined in the question. It's just an example of a function that takes a callback. Don't overthink it. – Felix Kling Mar 18 '17 at 23:05
  • 1
    *"var self = this. As mentioned this does not work in javacript classes."* You can easily do `var self = this; this.waitTimer= setTimeout(function() { self.waitForPlayers(); }, 5000)` (that's not better but shows that it "does work"). – Felix Kling Mar 18 '17 at 23:09
  • In the duplicate there is also the section *"Common problem: Using object methods as callbacks / event handlers"* which shows: `this.method.bind(this)`. If you think you don't have a good understanding of what functions actually are in JavaScript, maybe http://eloquentjavascript.net/03_functions.html and http://eloquentjavascript.net/04_data.html#h_fkrGgDyRWc help to clear that up. – Felix Kling Mar 18 '17 at 23:11
  • @JohnLittle regarding the large functions, I don't follow that reasoning. Putting 30 lines of code inside several method definitions doesn't make the enclosing class unmanageable either, does it? – Bergi Mar 18 '17 at 23:11

0 Answers0