Socket IO事件多次触发NodeJS

Posted

技术标签:

【中文标题】Socket IO事件多次触发NodeJS【英文标题】:Socket IO event firing multiple times NodeJS 【发布时间】:2019-07-05 15:49:20 【问题描述】:

我正在使用 socket.IO 在 NodeJS 和 android 中构建一个测验应用程序,

当我从服务器发出事件quizzoStatus 时遇到问题,该事件第一次触发一次,第二次触发两次,依此类推。

这里附上我的代码sn-p

///server side: NodeJS
socket.on('sendQuizzoAnsPoints', async (data)=>
          try 
              const obj = JSON.parse(data);
              const game = await QuizzoPlayModel.findOne(_id:obj.gameId);
              const player = await UserModel.findOne(_id: game.playerId);
              const opponent = await UserModel.findOne(_id: game.opponentId);
              if(obj.userId == game.opponentId)
                  let update = 
                      opponentPoints: game.opponentPoints + obj.points || 0,
                      opponentWA: game.opponentWA + obj.wrongAns || 0,
                  ;
                  await QuizzoPlayModel.findByIdAndUpdate(obj.gameId, update).lean().exec();
                  userNamespace.to(player.socketId).emit('quizzoStatus', 
                      fullName: opponent.fullName,
                      points: game.playerPoints + obj.points,
                      wrongAns: obj.wrongAns,
                      gameId: obj.gameId
                  );
              
              if(obj.userId == game.playerId) 
                  let update = 
                      playerPoints: game.playerPoints + obj.points || 0,
                      playerWA: game.playerWA + obj.wrongAns || 0,
                  ;
                  await QuizzoPlayModel.findByIdAndUpdate(obj.gameId, update).lean().exec();
                  userNamespace.to(opponent.socketId).emit('quizzoStatus', 
                      fullName: player.fullName,
                      points: game.playerPoints+ obj.points,
                      wrongAns: obj.wrongAns,
                      gameId: obj.gameId
                  );
              
           catch (e) 
              console.log(e);
          
        );

在这里我监听一个名为 sendQuizzoAnsPoints 的事件,然后在另一个名为 quizzoStatus 的事件中向玩家或对手发出一个事件。

quizzoStatus 事件从服务器多次触发到 android。 这里我附上了android代码

/// Android code
socket.emit("sendQuizzoAnsPoints", new Gson().toJson(quizzoStatusRequestDto)); 
socket.on("quizzoStatus", new Emitter.Listener()
           @Override
           public void call(Object... args)
               runOnUiThread(new Runnable()
                   @Override
                   public void run()
                       Log.e("opponet point", opponentPoints + " " + quizzoStatusResponseDto.getPoints());
                   
               );
           
       );

【问题讨论】:

似乎您的客户端(android)多次连接到服务器 我已经查过了,客户端连接了一次,但同时有两个或多个客户端从不同的设备连接。 每台设备都连接同一个ID? 不,每台设备都使用不同的 ID 连接。 @ŞivāSankĂr 服务器重启后记录所有连接的设备(ID)。只需将console.log() 放在socket.join() 之前即可 【参考方案1】:

问题出在Android。您每次都在分配新的侦听器,而不会删除前一个侦听器。您需要创建该 Emmiter 侦听器的变量,并在工作完成后将其删除到 onDestroy 或其他地方:

    //variable of Emmiter.Listener
    Emmiter.Listener quizzoStatus = new Emitter.Listener()
        @Override public void call(Object... args)
            runOnUiThread(new Runnable()
                @Override public void run()
                    Log.e("opponet point", opponentPoints + " " + quizzoStatusResponseDto.getPoints());
                
            );
        
    ;

    //assigning the listener
    socket.on("quizzoStatus", quizzoStatus);
    . . . .
    @Override protected void onDestroy()
        super.onDestroy();
        //removing the listener...
        socket.off("quizzoStatus", quizzoStatus);
    

希望这会奏效

【讨论】:

这在上传照片/媒体后从 onActivityResult 返回时也很有用...附加了较早的侦听器并附加了新的侦听器...对我来说它适用于 onStop

以上是关于Socket IO事件多次触发NodeJS的主要内容,如果未能解决你的问题,请参考以下文章

socket.on事件被多次触发

如何在前端获取 socket.on 函数?事件被触发和处理。我正在使用 socket.io、NodeJS 服务器和 Redis.io

Socket.io-防止触发多个事件

socket.io 监听器在功能性 React 中触发太多次

在 MongoDB 中使用带有 Socket.io 的 Change Stream 时,“更改”被多次触发

NodeJS、Express 和多事的 Socket.io