Socket.io事件侦听器多次调用,即使它仅从我的节点js服务器发出一次也是如此

时间:2018-10-02 04:36:47

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

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

现在,为了帮助我更好地提出问题,请考虑将会话视为我们在一个房间中进行的聊天,而离开房间将是会话结束。

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

因此,为了进一步明确解释, 在第一届会议上,它按预期工作... 每次聊天只有一条消息。

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

深入研究堆栈溢出之后,最可能的原因是我正在添加侦听器,即使该侦听器已经存在。因此,这使得聊天应用程序表现得很有趣,在聊天框中再次重复了相同的文本,并多次被调用。

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

以下是我的代码段: Angualar客户:

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) => {
    ....
  });

});

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

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 () {
    ....
  }
}]);

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

1 个答案:

答案 0 :(得分:0)

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

我顺便使用了off()函数。

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

}