2

I have a node.js server running a simple socket.io service

When I reference this.io.sockets in order to establish a "connection" handler function, it works fine. But if I later reference this.io.sockets, I get an an error

TypeError: Cannot read property 'sockets' of undefined

I'm pretty new to node.js so am not sure what I am doing wrong here.

Code:

var app = require('http').createServer();
var port = 8080;
app.listen(port);

function Serv() {
    this.io = require('socket.io')(app)
    this.addHandlers()
}

Serv.prototype.addHandlers = function () {    
    this.io.sockets.on("connection", function (socket) {
        console.log('new connection');        
        socket.on('disconnect', function () {
            console.log('disconnection');            
            if (this.io.sockets.adapter.rooms[phn] != null) { //Causes undefined error..
                //do something
            }
        });        
        socket.on(SOCKETEVENTMESSAGE, function (data) {            
            if (this.io.sockets.adapter.rooms[phn] != null) { //Causes undefined error..
                //do something
            }
        });
    });
};

// Start the  server
var serv = new Serv();
console.log('socket.io listening on ' + port);
Aleksandr M
  • 23,647
  • 12
  • 63
  • 129
Zigglzworth
  • 6,265
  • 7
  • 59
  • 101

2 Answers2

0

As you can see, the issue is obvious

this.io.sockets.on("connection", function (socket) {

Listener will be called whenever a connection happens, therefore the scope(this) will be different.

What you should be doing is, there are at least three ways, but I'd suggest one

Save the scope to a variable and close in by the listener like

Serv.prototype.addHandlers = function () {    
    var _this = this;
    this.io.sockets.on("connection", function (socket) {
        console.log('new connection');        
        socket.on('disconnect', function () {
            console.log('disconnection');            
            if (_this.io.sockets.adapter.rooms[phn] != null) {
                //do something
            }
        });     
code-jaff
  • 8,472
  • 4
  • 30
  • 52
0

The problem is that whenever you declare a function as a callback to your socket events, the function is given its own scope/context. This means that you lose the value of this. By default, in that situation, this actually refers to whatever context socket has run the callback function in.

JavaScript comes with a built in way to ensure that the context you want is used: bind

Serv.prototype.addHandlers = function () {    
    this.io.sockets.on("connection", function (socket) {
        console.log('new connection');        
        socket.on('disconnect', function () {
            console.log('disconnection');            
            if (this.io.sockets.adapter.rooms[phn] != null) { 'this' has correct value
                //do something
            }
        }.bind(this));        
        socket.on(SOCKETEVENTMESSAGE, function (data) {            
            if (this.io.sockets.adapter.rooms[phn] != null) { 'this' has correct value
                //do something
            }
        }.bind(this));
    }.bind(this));
};

To save yourself from getting too far into callback hell, you could declare the functions individually, something like this:

Serv.prototype.addHandlers = function () {
    var onDisconnect = function () {
        console.log('disconnection');            
        if (this.io.sockets.adapter.rooms[phn] != null) {
            //do something
        }
    }.bind(this);

    var handleEvent = function (data) {
        if (this.io.sockets.adapter.rooms[phn] != null) {
            //do something
        }
    }.bind(this);

    function onConnect (socket) {
        console.log('new connection');        
        socket.on('disconnect', onDisconnect);
        socket.on(SOCKETEVENTMESSAGE, onHandleEvent);
    }; // 'this' isn't required, so no binding necessary

    this.io.sockets.on("connection", onConnect);
};
kevatron400
  • 65
  • 1
  • 6