简体   繁体   English

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

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

I'm currently wondering about what could be the best programming practice in this case: 我目前想知道在这种情况下什么是最好的编程实践:

Let's say I've got client connected to my server. 假设我已将客户端连接到我的服务器。 And this client is asking the server for authentication with an auth event and his username. 此客户端要求服务器使用auth事件和用户名进行身份验证。

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

In this simple case, server is responding with an auth_succeed event with the users's id. 在这个简单的情况下,服务器使用用户的id响应auth_succeed事件。

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

So my question is, when or where should I bind the listener for the auth_succeed event in the client ? 所以我的问题是,何时何地应该在客户端绑定监听器以获取auth_succeed事件? There's two ways for me : 我有两种方式:

Before emitting, which ensures, I guess, that the response event will always be properly handled, but leads to some spaghetti code. 在发射之前,我想,这确保响应事件将始终得到妥善处理,但会导致一些意大利面条代码。 Ex: 例如:

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

Or after emitting, which leads to cleaner code, but could possibly, I guess again, miss the event if sended quick enough. 或者在发射之后,这导致更清晰的代码,但可能,我想再次,如果发送得足够快,可以错过这个事件。 Ex: 例如:

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

What's your thoughts about that problem ? 你对这个问题有什么看法?

Since the response from the emit should be asynchronous, and the client-side JS is synchronous in nature, the socket.on('auth_succeed' binding will happen before the callback from the auth event. 由于来自emit的响应应该是异步的,并且客户端JS本质上是同步的,所以socket.on('auth_succeed'绑定将在来自auth事件的回调之前发生。


The following flow will happen on the client... 客户端将发生以下流程...

// 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

Sometime after the enclosing scope/function is done executing the event of 'auth_succeed' be raised. 在完成封闭范围/功能之后的某个时间执行“auth_succeed”事件。


You may also want to consider breaking out your event handlers... 您可能还想考虑打破您的事件处理程序......

socket.on('auth_succeed', onAuthSucceed.bind(null, socket));
socket.emit('auth', 'john');

// ... elsewhere ...

function onAuthSucceed(socket, id) {
  // handle message from server
}

This will reduce the noise with your binding, and your signal event, regardless of if you choose to bind or emit first. 无论您选择先绑定还是先发射,这都会降低绑定和信号事件的噪音。

By having the function require anything it needs, and using binding for the event, the method in question can be in a separate file/module, and more easily tested in isolation. 通过使该函数需要它需要的任何东西,并使用事件的绑定,所讨论的方法可以在单独的文件/模块中,并且更容易单独测试。

The socket.io docs , in Migrating from 0.9, do a great job of showing how to authenticate sockets in 1.0. socket.io docs ,在Migrating from 0.9中,很好地展示了如何在1.0中验证套接字。

An example for you would be: 你的一个例子是:

You should create an authentication middleware to handle this. 您应该创建一个身份验证中间件来处理这个问题。

Create a controller called authorization.js: 创建一个名为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();
}

In index.js simply attach the middleware with io.use : 在index.js中只需使用io.use附加中间件:

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

Using io.set has been depreciated for io.use() since socket.io 1.0. 从socket.io 1.0开始,对io.use()使用io.set已经过折旧。

You can then let the client know that they have successfully authorized and connected by emitting auth_suceed on the connection event because with the new middleware in place, a socket will not be able to connect unless they successfully authorize. 然后,您可以通过在连接事件上发出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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM