NodeJS&Socket.IO:发出请求事件并获取响应,我应该在何时/何地绑定侦听器

NodeJS & Socket.IO: Emit a request event and get the response, when/where should I bind the listener?

本文关键字:我应该 响应 获取 何时 侦听器 绑定 何地 事件 Socket amp IO      更新时间:2023-09-26

我目前想知道在这种情况下最好的编程实践是什么:

假设我已将客户端连接到我的服务器。此客户端要求服务器使用 auth 事件及其用户名进行身份验证。

socket = io();
socket.emit('auth', "John");

在这个简单的情况下,服务器使用用户的 id 响应auth_succeed事件。

io.on('connection', function(socket) {
    socket.on('auth', function(username) {
        socket.emit('auth_succeed', id);
    }
}

所以我的问题是,我应该在何时何地绑定客户端中auth_succeed事件的侦听器?我有两种方法:

在发出之前,我想这确保了响应事件将始终得到正确处理,但会导致一些意大利面条代码。前任:

socket = io();
socket.on('auth_succeed', function(id){
    //Do some post-auth stuff here
}); 
socket.emit('auth', "John");

或者在发出后,这会导致更干净的代码,但如果发送得足够快,我猜可能会错过事件。前任:

socket = io();
socket.emit('auth', "John");
socket.on('auth_succeed', function(id){
    //Do some post-auth stuff here
}); 

你对这个问题有什么看法?

由于来自 emit 的响应应该是异步的,并且客户端 JS 本质上是同步的,因此socket.on('auth_succeed'绑定将在 auth 事件的回调之前发生。


以程将在客户端上发生...

// EXECUTION SCOPE BEGINS
...
// this will send a message to the server
// the message and/or response will be sent asynchronously
socket.emit('auth', 'John'); 
// so your code will continue before you get anything from the server
//which means the following binding will happen before any response to the above emit
socket.on('auth_succeed', function(id){
  //... handle message from server ...
});
...
// EXECUTION SCOPE ENDS

在封闭作用域/函数执行完成后的某个时间,将引发"auth_succeed"事件。


您可能还需要考虑分解事件处理程序...

socket.on('auth_succeed', onAuthSucceed.bind(null, socket));
socket.emit('auth', 'john');
// ... elsewhere ...
function onAuthSucceed(socket, id) {
  // handle message from server
}

这将减少绑定和信号事件的干扰,无论您选择先绑定还是先发射。

通过让函数需要它需要的任何内容,并对事件使用绑定,所讨论的方法可以位于单独的文件/模块中,并且更容易单独测试。

0.9 迁移中的 socket.io 文档很好地展示了如何在 1.0 中对套接字进行身份验证。

您的一个例子是:

您应该创建一个身份验证中间件来处理此问题。

创建一个名为 authorization.js 的控制器:

/**
 * Socket.io middleware that that authorizes clients
 * @param {object} socket
 * @param {function} next
 */
module.exports = function(socket, next) {
    // do some custom auth here
    var handshakeData = socket.request;
    // make sure the handshake data looks good with some
    // custom logic
    // if doesn't you can do this:
    // next(new Error('not authorized');
    // else just call next
    next();
}

在索引中.js只需使用 io.use 附加中间件:

var authorizeSockets = require('./controllers/authorization');
io.use(authorizeSockets);

自 socket.io 1.0 以来,使用 io.set 已折旧了 io.use()

然后,您可以通过在连接事件上发出auth_suceed来让客户端知道它们已成功授权和连接,因为使用新的中间件后,套接字将无法连接,除非它们成功授权。

io.on('connection', function(socket){
    socket.emit('auth_succeed', yourPayloadHere);
});
socket.set('authorization',function(request,callback){
// check authorization for username
// set global variable flag for valid/invalid username.
if(valid_uname){
return(null,true)
}
else{
return(null,false);
}
)};
//Now on socket.on check global variable flag.
//emit when needed.