【问题标题】:How to leave a socket room with vue-socket and rejoin without duplicate messages?如何离开带有 vue-socket 的套接字房间并重新加入而不重复消息?
【发布时间】:2021-01-28 21:13:51
【问题描述】:

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

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

到目前为止,我已经尝试了所有能找到的方法,但都无法正常工作。

我在客户端尝试过,在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)。

我想要做的就是不刷新,当我离开页面时,在此之前,用户可以离开房间,当他们返回时,他们可以重新加入,不会出现重复的消息。

我现在正在尝试仔细阅读源代码。

【问题讨论】:

    标签: node.js express vue.js socket.io vue-socket.io


    【解决方案1】:

    在这里完全披露,我没有阅读 roberfoenix 提出的完整回复,但这是 socket.io 的一个常见问题,它归结为多次调用“on”事件。

    当你为你的套接字创建一个 .on 事件时,它是一个绑定,你可以多次绑定到同一个事件。

    我的假设是,当用户点击一个页面时,你会运行类似

    socket.on("joinRoom", 数据)

    这反过来会说加入房间,从 Mongo(或其他东西)中提取您的消息,然后发送到房间(旁注,使用 .once on 可以帮助您在用户时不会向每个用户发送加入一个房间)

    现在你离开房间,调用 socket.emit('leaveRoom',room),冷静下来你离开房间,然后你回到房间,猜猜你现在刚刚绑定到同一个 on 事件,所以当您发出,它会向该用户发出两次等。

    我们解决这个问题的方法是将所有的 on-events 放入一个函数并调用该函数一次。因此,用户加入一个页面,这将运行 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 进行改进,或者可以在连接时完成,但如果用户重新连接,它可能会再次运行。

    【讨论】:

      【解决方案2】:

      如果您使用 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');
      

      对任何以重复形式给您造成麻烦的事件执行此操作。首先你会得到重复的原因,特别是在离开房间后重新加入帖子时,是因为以前的事件监听器仍在运行,现在单个用户将扮演两个或多个监听器的角色。

      另一种可能性是,您将消息发送给所有人,包括原始发件人,而您最有可能将其发送给除发件人 (check here for socket.io emit cheatsheet) 之外的所有人。

      如果上述方法不能为您解决问题,请确保您实际上是在离开房间,并在服务器端这样做。您可以通过在离开路由之前向服务器发出信号(如果您使用的是反应式单页应用程序)、在服务器端接收它并在您的 io.on("connection", function(socket) {}) 实例中调用“socket.leave(yourRoomName)”来实现这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-07
        • 1970-01-01
        • 1970-01-01
        • 2021-08-23
        • 1970-01-01
        • 1970-01-01
        • 2019-06-20
        相关资源
        最近更新 更多