在“连接”上使用 socket.io 服务器持久化数据
Posted
技术标签:
【中文标题】在“连接”上使用 socket.io 服务器持久化数据【英文标题】:Persisting data with socket.io server on 'connect' 【发布时间】:2017-01-14 07:55:28 【问题描述】:我将 socket.io 与 MongoDB 和 Promise 一起使用。我想在建立会话时在 Mongo 中保存一些数据,并且在保存这些数据之前不一定能正确处理进一步的套接字事件。
// Simplified code
io.sockets.on('connection', function(socket)
var req = socket.handshake;
mongoDbPromise.then(function (db)
return db.collection('mycollection').insert(some_user_data: req.query.some_user_data);
).then(function (insertResult)
// do some other work
).catch(function (error)
socket.disconnect();
logger.info(error);
);
我遇到的问题是 connection
套接字事件在此连接处理程序返回后立即发出,但是当 MongoDB 的承诺解决并且我的 then
处理程序被调用时,设置连接的工作仍在继续。在收到connection
后立即发出请求的客户端会看到应用处于不一致状态。
我可以看到两种方法来解决这个问题:
1) 使用某种回调来控制何时发出connection
。不过,我在 socket.io 文档中没有看到任何迹象表明可以这样做。
2) 不要使用connection
来表示套接字已准备就绪,而是使用其他一些自定义事件(我们称之为connection_established
)并在then
处理程序中发出它。
选项 1 可能吗?有没有更好的方法来处理这种情况?
【问题讨论】:
几周前,我实现了this article 中描述的方法,对我来说效果很好。基本上,您允许客户端成功连接,但在完成身份验证/数据查找后,有第二个商定的握手消息。基本上是您的选择 2)。 【参考方案1】:好吧,如果您在连接处理程序中要做异步工作(您这样做),那么在您完成连接处理程序中的工作之前,您不能阻止客户端认为它已连接。你有几个选择来解决这个问题:
您可以使用中间件挂钩到 socket.io 连接的身份验证过程,并使用该功能来控制事物。如果您的数据库操作失败,您实际上会表现得好像连接未授权,这将断开连接。
您可以将您自己的“connectionReady”消息发送给客户端,并设置客户端在收到“connectionReady”消息之前不向您发送任何内容,您只会在连接完成后发送该消息事情(听起来你已经有了这个想法,想到了 connection_established)。
socket.io v1 及更高版本中的身份验证过程可以使用这样的中间件完成:
io.use(function(socket, next)
var req = socket.handshake;
mongoDbPromise.then(function (db)
return db.collection('mycollection').insert(some_user_data: req.query.some_user_data);
).then(function (insertResult)
// do some other work
// socket is now ready to go
next();
).catch(function (error)
// error on authentication
next(new Error('not authorized');
logger.info(error);
);
);
connectionReady
进程可以这样工作:
// Simplified code
io.sockets.on('connection', function(socket)
var req = socket.handshake;
mongoDbPromise.then(function (db)
return db.collection('mycollection').insert(some_user_data: req.query.some_user_data);
).then(function (insertResult)
// do some other work
// send client a message indicating that the connection is now ready
socket.emit("connectionReady", true);
).catch(function (error)
socket.disconnect();
logger.info(error);
);
【讨论】:
@Pathogen - 这回答了你的问题吗? 几乎!我忽略了一个细节:我现在坚持使用 socket.io 0.9x。next
回调正是我希望在授权者中使用的,但我坚持使用旧风格的 io.set('authorization', ... )
API 进行授权。除非0.9x可以使用中间件进行授权?
@Pathogen - 是的,0.9x 与 1.0+ 有很大不同。如果您寻求帮助,您将始终不得不提及,因为几乎没有任何 0.9x 开发,甚至更少的文档。如果这对您有所帮助,请向社区表明这一点,然后单击答案左侧的绿色复选标记。这也将为您在堆栈溢出时获得一些声誉积分,以遵循正确的程序。以上是关于在“连接”上使用 socket.io 服务器持久化数据的主要内容,如果未能解决你的问题,请参考以下文章
如何在 android 上检查 socket.io 连接或断开连接?