当我加入房间,然后离开路线返回,然后使用我建立的聊天室时,我收到的消息数量是我离开和重新加入的消息数量的两倍。
当我努力刷新时,这个问题就消失了。
到目前为止,我已经尝试了我能找到的一切,但都无法使其发挥作用。
在beforeRouteLeave
、beforeDestroy
和window.onbeforeunload
期间,我在客户端进行了尝试
this.$socket.removeListener("insertListener");
->尝试了所有this.$socket = null
this.$socket.connected = false
this.$socket.disconnected = true
this.$socket.removeAllListeners()
this.$socket.disconnect()
在相同的事件中,我还发送了一个this.$socket.emit("leaveChat", roomId)
,然后在服务器端尝试在io.on("connection")
接收器socket.on("leaveChat", function(roomId) {})
内执行以下操作:
socket.leave(roomId)
->这是根据文档应该做的工作socket.disconnect()
socket.off()
——似乎已弃用socket.removeAllListeners(roomId)
我尝试了很多其他事情,但我记不清了,但如果我记得的话,会更新帖子。
要么它以某种方式断开连接,重新加入时,以前的侦听器或其他东西仍然存在,这意味着所有消息都会被接收*次重新加入。或者,如果我断开连接,我似乎无法重新连接。
加入时,我向服务器发送房间id,并使用socket.join(roomId(.
我所想做的就是不刷新,当我离开页面时,在此之前,用户可以离开房间,当他们返回时,他们可以重新加入,不会出现重复的消息。
我现在正试图仔细阅读源代码。
此处完全公开,我没有阅读roberfoenix提出的完整响应,但这是socket.io的常见问题,归根结底是多次调用"on"事件。
当您为套接字创建.on事件时,它是一个绑定,您可以多次绑定到同一事件。
我的假设是,当用户点击一个页面时,你会运行类似的东西
socket.on("joinRoom",数据(
这反过来会说加入房间,从Mongo(或其他东西(提取你的消息,然后发送到房间(附带说明,使用.oonce可以帮助你,这样当用户加入房间时,你就不会向每个用户发送(
现在你离开房间,调用socket.emit("leaveRoom",房间(,冷却你离开房间后,你回到房间,猜测你现在刚刚绑定到同一个事件上的内容,所以当你发射时,它会向该用户发射两次,等等
我们解决这一问题的方法是将所有on事件放入一个函数中,并调用该函数一次。因此,用户加入一个页面,这将运行类似socketInit((的函数;
socketInit函数将具有类似于的内容
function socketInit(){
if (init === false){
//Cool it has not run, we will bind our on events
socket.on("event")
socket.on("otherEvent")
init = true;
}
}
基本上,init是一个全局变量,如果为false,请绑定事件,否则不要重新绑定。
这可以通过使用promis进行改进,也可以在连接时进行,但如果用户重新连接,它可能会再次运行。
如果您正在使用Vue Socket,并且在尝试了所有内容后感觉有点疯狂,那么这可能是您的解决方案
事实证明,挑战核心假设和从头开始的调查是有回报的。你可能在Socket.io中深深忘记了自己,以至于忘记了自己在使用Vue Socket。
在我的案例中,解决方案是使用Vue Socket内置的取消订阅功能。
使用Vue Socket,您最初可以订阅事件的方式之一如下:
this.sockets.subscribe('EVENT_NAME', (data) => {
this.msg = data.message;
});
因为您使用的是Vue Socket,而不是常规的,所以您还需要在离开房间之前使用Vue Socket的方式取消预订(除非您正在寻找非常定制的解决方案(。这就是为什么我怀疑我尝试的许多其他事情都不起作用,几乎什么都没做!
你这样做的方式如下:
this.sockets.unsubscribe('EVENT_NAME');
对于任何以重复形式给您带来麻烦的事件,请执行此操作。首先,你会得到重复的原因,尤其是在离开房间重新加入帖子时,是因为以前的事件侦听器仍在运行,而现在单个用户将扮演两个或多个侦听器的角色。
另一种可能性是,你将消息发送给所有人,包括原始发件人,而你很可能会将消息发送到除发件人之外的其他所有人(请查看此处的socket.io emit cheatsheet(。
如果以上这些都不能帮你解决问题,那么请确保你真的离开了房间,并在服务器端这样做。您可以通过在离开路由之前向服务器发出信号(如果您使用的是反应式单页应用程序(,在服务器端接收信号,并在io.on("connection", function(socket) {})
实例中调用"socket.leave(yourRoomName)
"来实现这一点。