我目前想知道在这种情况下最好的编程实践是什么:
假设我已将客户端连接到我的服务器。此客户端要求服务器使用 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.