Node.js - socket.io - 对 io.sockets 的引用突然未定义

Node.js - socket.io - reference to io.sockets suddenly undefined

我有一个 node.js 服务器 运行 一个简单的 socket.io 服务

当我引用 this.io.sockets 以建立 "connection" 处理函数时,它工作正常。但是如果我稍后引用 this.io.sockets,我会得到一个错误

TypeError: Cannot read property 'sockets' of undefined

我是 node.js 的新手,所以不确定我做错了什么。

代码:

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);

如您所见,问题很明显

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

每当连接发生时都会调用监听器,因此作用域(this)会有所不同。

你应该做的是,至少有三种方法,但我建议一种

将作用域保存到一个变量并由监听器关闭,如

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
            }
        });     

问题在于,无论何时将函数声明为对套接字事件的回调,都会为该函数提供自己的 scope/context。这意味着您丢失了 this 的值。默认情况下,在那种情况下,this 实际上指的是具有 运行 回调函数的任何上下文套接字。

JavaScript 内置了一种方法来确保使用您想要的上下文: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));
};

为了避免在 callback hell 中走得太远,您可以单独声明函数,如下所示:

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);
};