【问题标题】:Socket.io event listener called multiple times even though it's emitted only once from my node js server多次调用 Socket.io 事件侦听器,即使它仅从我的节点 js 服务器发出一次
【发布时间】:2020-01-17 18:31:50
【问题描述】:

所以我在 AngularJS 1.x 客户端上有一个名为 newMessage 的自定义套接字事件侦听器。

现在为了帮助我更好地提出这个问题,请将会话想象成我们在一个房间里聊天,走出房间就是会话的结束。

现在,即使我的服务器只发出一次“newMessage”事件,我的客户端侦听器也会被触发多次,并且次数等于我们之前的会话数。

所以为了进一步解释清楚, 在第一次会议上,它按预期工作...... 每次聊天只有一条消息。

但是在第二次加入聊天时,听众会被解雇两次。当第三个会话运行时,你猜了 3 次。

深入挖掘堆栈溢出后,最可能的原因是我正在添加侦听器,即使它已经存在。所以这使得聊天应用程序以一种有趣的方式运行,相同的文本在我的聊天框中再次重复并被多次调用。

如果 newMesaage 侦听器已经到位,有人可以帮助我如何不继续添加它。我尝试了 socket.hasListener 并添加如果它不存在但它仍然无法正常工作

这是我的代码中的 sn-ps: 角度客户端:

socket.on('newMessage', function (message) {
console.log(message);
var html = `<p>${message.from} : ${message.text}</p>`;
$('.chat-box').append(html);
$scope.scrollToBottom();
});

节点服务器:

io.in(room).emit('newMessage', generateMessage('Admin:', `Welcome`));

在我的服务器代码中也向该事件发出另一个信号

io.in(room).emit('newMessage', generateMessage(user.username, message.text));

generateMessage() 是我服务器上的一个 util js 文件,它没有问题。

所以在每个 socket.on(newMessage) 上,都会发生一件奇怪的事情。即使在服务器上它只发出一次,它也会被多次调用。另一个有趣的事情是它重复了我们进入套接字连接而没有断开连接的次数。

同样在断开连接时(例如重新加载而不是在我的角度路由),会话从 #1 重新开始。但随着更多会话的发生,我提到的行为会被观察到。

我觉得这很奇怪...有人请帮助我,我们将不胜感激。谢谢!

编辑:添加更多代码

这是我在服务器上 app.js 中的套接字代码。给出了发出此事件的两种方法。其他方法我缩短了,因为我发现它与这个事件错误无关。

io.on('connection', socket => {
  var currentRoomId;
  socket.on('disconnect', () => {
    io.in(currentRoomId).emit('endgameclient');
    onlineRooms.forEach((room, i) => {
      if (room === currentRoomId) {
        onlineRooms.splice(i, 1);
      }
    });
  });
  socket.on('startgame', (secret, callback) => {
    var room = secret.toString();
    var curplayers = players.getPlayerList(room);
    io.in(room).emit('startgameclient', players.getPlayerList(room));
    if (curplayers) {
      io.in(room).emit('newMessage', generateMessage('Admin:', `Game on ${curplayers[0].username} & ${curplayers[1].username}`));
    }
    callback();
  });
  socket.on('createNewMessage', (message, callback) => {
    var room = message.secret.toString();
    var player = players.getPlayer(socket.id);
    io.in(room).emit('newMessage', generateMessage(player.username, message.text));
    callback(null, true);
  });
  socket.on('playerjoin', (joinUser, callback) => {
    ....
  });
  socket.on('getplayers', (secret, callback) => {
    ...
  });
  socket.on('checkplayercount', (secret, callback) => {
    ...
  });
  socket.on('getrooms', (none, callback) => {
    ....
  });
  socket.on('playerleft', (secret) => {
    ....
  });

});

这是我的 Angular 客户端代码,我在其中给出了两种处理消息传递的方法。

app.controller('TictactoeCtrl', ['$scope', '$transitions', '$http', '$state', '$stateParams', 'authFactory', 'playersService', 'socket', function ($scope, $transitions, $http, $state, $stateParams, authFactory, playersService, socket) {

  socket.on('disconnect', function () {

  });

  socket.on('newMessage', function (message) {
    console.log(message);
    var html = `<p>${message.from} : ${message.text}</p>`;
    $('.chat-box').append(html);
    $scope.scrollToBottom();
  });

  $scope.sendNewMessage = function (e) {
    socket.emit('createNewMessage', { text: $("#message-input").val(), secret: $scope.secret }, function () {
      $("#message-input").val('').blur();
    });
  };

  socket.on('updateplayers', function (players) {
    ....
  });

  socket.on('canstartgame', function (players) {
    ....
  });

  socket.on('startgameclient', function (players) {
    ....
  });

  socket.on('endgameclient', function () {
    ....
  });

  $scope.startGame = function () {
    ...
  };

  $scope.goHome = function () {
    ...
  };
  $scope.logOut = function () {
    ....
  };

  $scope.scrollToBottom = function () {
    ....
  }
}]);

希望这能更详细地描述我的代码。

【问题讨论】:

  • 通常这种症状是由于在其他事件处理程序中添加了 socket.io 事件侦听器引起的,导致您安装了重复的事件处理程序,从而导致您认为消息被多次接收。请向我们展示更多您的代码,以便我们查看是否是这种情况。特别是向我们展示您认为重复的事件处理程序的上下文,以便我们可以更好地建议如何避免重复。
  • 嘿,感谢您的评论。我在另一个问题上也读到了这一点,但是我的 socket.on('newMessage') 不在任何事件处理程序的范围内,无论是 Angular 还是套接字事件。它的词法范围在视图的控制器内,而不是在任何其他处理程序内您想在客户端和服务器上的方法中看到更多代码,您的意思是通过提供更多上下文?再次感谢!
  • 我们需要查看包含您添加消息处理程序的所有内容(所有包含函数)以及它们的调用方式。
  • 嘿 jrfriend00,请在编辑部分查看问题。已经从我的节点 js 服务器代码和 angularjs 客户端代码中添加了更多代码...如果您发现它有问题,请告诉我...
  • 希望比我更了解 angularjs 的人现在可以帮助您。

标签: javascript angularjs node.js sockets socket.io


【解决方案1】:

所以每次我通过视图进入这个角度控制器时,我都会创建套接字事件处理程序的新实例。因此,即使它不在事件处理程序中,每次我来到这个特定的控制器时它仍然被复制,因此代码的行为方式是这样的。因此,为了解决这个问题,当我使用 $transition 离开视图时,我只是关闭了所有事件侦听器。瞧,它有效!

顺便说一句,我使用了 off() 函数。

if ($transition.$from().name === 'tictactoe') {
    socket.off()

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 2020-12-23
    • 2017-01-31
    • 2021-10-29
    • 2021-12-31
    • 2019-10-30
    相关资源
    最近更新 更多