问题描述
当我加入会议室,然后离开路线并返回,然后使用我建立的聊天室时,我收到离开并重新加入的次数是*消息数量的两倍。
当我硬刷新时,这个问题就消失了。
到目前为止,我已经尝试了所有可以找到的东西,但无法使其正常工作。
我在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(或其他东西)提取您的消息,然后发送到聊天室(旁注,使用.once on会有所帮助,因此当用户开个房间)
现在您离开房间,调用socket.emit('leaveRoom',room),让您凉爽离开房间,然后回到房间,猜测现在绑定到相同事件的对象是什么,所以当您发出,它向该用户发出两次,依此类推。
我们解决此问题的方法是将所有活动事件放入一个函数中,然后调用该函数一次。因此,用户加入页面后,将运行类似于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,所以您还需要在离开房间之前使用 Vue Socket的方式退订(除非您正在寻找一种非常自定义的解决方案) 。这就是为什么我怀疑我尝试过的许多其他方法都行不通并且几乎什么也没做的原因!
您的操作方式如下:
this.sockets.unsubscribe('EVENT_NAME');
对于任何导致您麻烦的事件,请以重复的方式进行。首先要获得重复的原因,尤其是在重新加入帖子离开房间后,是因为先前的事件侦听器仍在运行,现在单个用户将扮演两个或多个侦听器的角色。 / p>
另一种可能性是,您最有可能将邮件发送给除发件人(check here for socket.io emit cheatsheet以外的其他所有人,而包括原始发件人的邮件。
如果以上方法不能解决您的问题,请确保您实际上已离开房间,并在服务器端这样做。您可以通过在离开路由之前(如果您使用的是反应性单页应用程序)向服务器发送信号,在服务器端接收它并在{{1}中调用'socket.leave(yourRoomName)
' }实例。