那么在'disconnect'
事件中socket的客户端作用域会发生什么?
我正在尝试避免我的node.js + mongoose + socket.io app中的恶劣赛车条件和逻辑缺陷。
范围是什么意思:
io.on('connection', function (client) {
///CLIENT SCOPE///
//define private vars, store and operate client's session info//
//recieving and sending client's socket signals//
}
一些背景:
比方说,例如,我通过查找room
并将user
写入此room
来实现一些操作数据库的函数。
但是,在room
(要写入)找到但用户尚未写入的那一刻,他断开连接。在断开连接事件时,我必须把他拉出他在db的最后一个房间,但是我不能,它现在还没有保存在数据库中。
我看到的唯一方法是在bool
事件上指定一个'disconnect'
值,我可以在将该人员保存到room
之前检查该事件,并且在true
don'的情况下拯救他。
我感到困惑的是 - 这个bool
能否在断开连接事件中存活,因为它保存在客户端的范围内。
范围会发生什么?在断开连接时它完全消失了吗?或者只有在完成依赖于此范围的所有内容时才会消失?
我正在使用'forceNew': true
强制socket.connect();
如果出现问题(假设)并且socket error
在没有用户真正离开网站的情况下立即执行套接字。
如果用户通过这个“旧”套接字重新连接,他是否在服务器上恢复了他的作用域,或者这个套接字的先前作用域在断开连接时已被清除,或者在'connection'
事件重新连接时被清除?
答案 0 :(得分:1)
只要运行使用该闭包的代码,client
闭包就会保持活动状态,因此您通常不必担心该问题。闭包本质上是Javascript中的一个对象,当没有活动代码引用闭包内的任何内容时,它只会被垃圾收集。
对于在写入数据库时断开套接字的并发问题,您应该认识到这是一个需要注意的问题。您需要做什么,具体取决于数据库的行为方式。由于node.js运行单线程,因此在处理任何断开连接事件之前,写入数据库的node.js代码将运行完成。这并不意味着数据库写入将在断开连接事件开始处理之前完成,但它确实意味着它已经被发送到数据库。因此,如果您的数据库按照接收它们的顺序处理多个请求,那么它可能只是做正确的事情,您将不会有任何额外的代码需要担心。
如果您的数据库在写入完成之前实际上可以处理删除(这似乎不太可能),那么您必须为此编写一些保护。最简单的概念是在给定用户的所有数据库操作上实现数据库队列。我可能会在其上创建一个带有通用DB方法的对象来实现此队列,并在每个client
闭包中创建一个单独的对象,这样它们就是给定用户的本地对象。当数据库操作正在进行时,此对象将具有一个标志,指示操作正在进行中。如果在设置此标志时调用了另一个数据库操作,则第二个操作将进入队列而不是直接发送到数据库。每次数据库操作完成时,它都会检查队列以查看是否有下一个操作正在等待运行。如果是这样,它会运行它。
仅供参考,我有一个简单的node.js应用程序(在带有温度传感器的Raspberry Pi上运行)记录温度数据,并且每隔一段时间它就会使用异步写入将数据写入磁盘。因为新的温度数据可能会在我处于异步写入数据的过程中到达,所以我遇到了类似的问题。我抽象了对象中数据的所有操作,实现了一个标志,指示我是否正在编写数据,如果有任何方法调用到达以修改数据,那么这些操作会进入队列并进行处理只有当写完了。
关于您的上一个问题,client
关闭中的io.on('connection', ...)
范围仅与该特定connection
事件相关联。如果你得到另一个connection
事件并因此触发该代码再次运行,那将创建一个与前一个无关的新的单独闭包,即使client
对象是相同的。通常情况下,这很好,因为此函数中的代码只会为新连接重新设置。