0

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

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

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

因此,为了进一步清楚地解释,在第一次会话中,它按预期工作......每次聊天只有一条消息。

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

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

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

以下是我的代码片段: Angular 客户端:

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

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

4

1 回答 1

0

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

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

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

}

于 2018-10-03T03:13:17.777 回答