如何在没有重复消息的情况下离开带有vue套接字的套接字室并重新加入



当我加入房间,然后离开路线返回,然后使用我建立的聊天室时,我收到的消息数量是我离开和重新加入的消息数量的两倍。

当我努力刷新时,这个问题就消失了。

到目前为止,我已经尝试了我能找到的一切,但都无法使其发挥作用。

beforeRouteLeavebeforeDestroywindow.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)"来实现这一点。

最新更新