因此,我在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 () {
....
}
}]);
希望这会更详细地描述我的代码。
答案 0 :(得分:0)
因此,每次通过视图进入此角度控制器时,我都会创建套接字事件处理程序的新实例。因此,即使它不在事件处理程序中,但每次我来到该特定控制器时,它仍然会被复制,因此代码的行为方式是这样的。因此,要解决此问题,我在使用$ transition离开视图时,仅关闭了所有事件侦听器。瞧,它有效!
我顺便使用了off()函数。
if ($transition.$from().name === 'tictactoe') {
socket.off()
}