0

My code looks as followed:

I have a socketAPI module which handles all the socket-traffic of the app:

var io = new socketIoServer();
var socketApi = {};
socketApi.io = io;

io.on('connection', function (client) {
    const SetupHandler = require ('./socket_handlers/setup-handler.js');
    setupHandler = new SetupHandler(client, arg1, arg2);
    setupHandler.bind();
}

then in the setup handler i got following code:

function SetupHandler(client,arg1,arg2) {
    this.client = client;
    socketApi.setups[lobby.id] = new Setup(lobby, scenario_id);
    this.setup = socketApi.setups[lobby.id];
    this.client.emit("test");                       //this works
}
SetupHandler.prototype.requestGameSetup = function(){
    // do stuff
    this.client.emit("test");  //doesnt work

};
SetupHandler.prototype.bind = function(){
    this.client.on('request_game_setup', this.requestGameSetup);
}
module.exports = SetupHandler;

it gives me following error:

/home/markus/WebstormProjects/penquest/socket_handlers/setup-handler.js:32
this.client.emit("test");
            ^

TypeError: this.client.emit is not a function
at Socket.SetupHandler.requestGameSetup (/home/markus/WebstormProjects/penquest/socket_handlers/setup-handler.js:32:17)
at Socket.emit (events.js:180:13)
at /home/markus/WebstormProjects/penquest/node_modules/socket.io/lib/socket.js:513:12

The idea here is to have one SetupHandler per client connection which handles all the events , do you have any ideas how i can accomplish this?

Markus
  • 17
  • 4
  • your this.client is not a socket instance or object please check the value for the same.emit is only possible on live and registered sockets – Neha Tawar Mar 28 '18 at 16:45

2 Answers2

0

Solution:

SetupHandler.prototype.requestGameSetup = () => {
// do stuff
this.client.emit("test");  //doesnt work };

Use => operator to get this scope inside prototype.

thatcoder
  • 367
  • 2
  • 9
0

The problem is that you're losing the value of this on this line of code:

this.client.on('request_game_setup', this.requestGameSetup);

Change it to:

this.client.on('request_game_setup', this.requestGameSetup.bind(this));

When you pass this.requestGameSetup, it's like you are doing this:

let fn = this.requestGameSetup;
this.client.on('request_game_setup', fn);

At this point, fn is just a reference to the requestGameSetup function and it is called without the object reference, thus the this value is not what you want. You can use .bind() to bind the desired value of this to it.


You could also not pass it directly like this:

this.client.on('request_game_setup', () => {
    this.requestGameSetup();
});

Here you're using the fat arrow function definition to preserve the value of this for you so you can then call this.requestGameSetup(). But, I prefer using .bind() since it seems to more directly do what you want it to do.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thank you very much, that solved my problem! Is there also a way to pass the `this` to the `requestGameSetup` without overwriting it? – Markus Mar 28 '18 at 18:59
  • @Markus - No, there is not. The value of `this` is determined by how a function is called, not by how it is passed. Since the caller in this case is the internals of the event notification, there's no way to ask it to call it the right way to set the right `this`. So, you have to override it yourself with one of the mechanisms above. – jfriend00 Mar 28 '18 at 22:58
  • @Markus - See [How `this` is determined in a function](https://stackoverflow.com/questions/28016664/when-you-pass-this-as-an-argument/28016676#28016676) for all the ways that the value of `this` is controlled. – jfriend00 Mar 28 '18 at 22:58