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

时间:2014-12-31 11:19:12

标签: javascript node.js socket.io

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

假设我已将客户端连接到我的服务器。此客户端要求服务器通过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
}); 

您对此问题的看法是什么?

3 个答案:

答案 0 :(得分:4)

由于来自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
}

无论您选择先绑定还是先发射,这都会降低绑定和信号事件的噪音。

通过让函数需要它需要的任何东西,并使用事件的绑定,有问题的方法可以在一个单独的文件/模块中,更容易单独测试。

答案 1 :(得分:1)

在迁移自0.9中的socket.io docs可以很好地展示如何在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();
}

在index.js中,只需将中间件附加到io.use

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

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

然后,您可以通过在连接事件上发出auth_suceed来让客户知道他们已成功授权和连接,因为新的中间件到位后,除非成功授权,否则套接字将无法连接。 / p>

io.on('connection', function(socket){
    socket.emit('auth_succeed', yourPayloadHere);
});

答案 2 :(得分:0)

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.