Socket.io 消息事件多次触发
Posted
技术标签:
【中文标题】Socket.io 消息事件多次触发【英文标题】:Socket.io message event firing multiple times 【发布时间】:2013-10-10 08:26:16 【问题描述】:我正在尝试学习 node 并开始使用 socket.io 创建一个 mashup 消息传输已经开始,但我遇到了一些麻烦。
消息事件被多次触发,导致一条消息多次出现在收件人的邮箱中。我已将套接字路由到 exports.chat
并且想知道这是否导致了问题?
缩小问题范围:消息触发的次数=客户端的连接顺序。也就是说,如果客户端第二次连接,他的消息将触发两次。客户端连接第三次。
这里是sn-p的代码:
exports.chat = function(io, pseudoArray, req, res)
res.render('chat', title: 'ChatPanel.');
var users = 0;
io.sockets.on('connection', function (socket) // First connection
users += 1;
// reloadUsers(io, users);
socket.on('message', function (data) // Broadcast the message to all
if(pseudoSet(socket))
var transmit = date : new Date().toISOString(), pseudo : returnPseudo(socket), message : data;
socket.broadcast.emit('message', transmit);
console.log("user "+ transmit['pseudo'] +" said \""+data+"\"");
);
socket.set('pseudo', req.session.user, function()
pseudoArray.push(req.session.user);
socket.emit('pseudoStatus', 'ok');
console.log("user " + req.session.user + " connected");
);
socket.on('disconnect', function () // Disconnection of the client
users -= 1;
// reloadUsers();
if (pseudoSet(socket))
var pseudo;
socket.get('pseudo', function(err, name)
pseudo = name;
);
var index = pseudoArray.indexOf(pseudo);
pseudo.slice(index - 1, 1);
);
);
;
【问题讨论】:
在您的断开连接处理程序中:带有 pseudo.slice 的部分应该在 getter 处理程序内。 ***.com/questions/23092624/… 【参考方案1】:socket.io 代码的整个部分必须在 external.chat 函数之外。 Socket IO 必须与 http/app 服务器绑定,你不应该在每个请求中处理它。
消息被触发的次数 = 客户端的连接顺序
本质上发生的是,每次新请求到达时,您都在为消息注册一个事件处理程序,因此它被触发的次数与您访问聊天 URL 的次数一样多。
io.socket.on('message', function (data) ...)
【讨论】:
我也面临同样的问题,有人可以帮我解决这个问题,这个问题是如何解决的,当我将代码更改为io.sockets.on('message'
它不起作用【参考方案2】:
所以我遇到了同样的问题。解决方案是在 socket.on('disconnect') 事件上关闭所有侦听器,这就是我的代码的样子 -
socket.on('disconnect', function ()
socket.removeAllListeners('send message');
socket.removeAllListeners('disconnect');
io.removeAllListeners('connection');
);
可能不需要在断开连接时调用它,不确定但我还是这样做了。
【讨论】:
这实际上并不能解决第二个客户端登录时的问题.. 只是当一个客户端断开连接时。仍然没有解决我的问题:/ 这是救命稻草。试图调试这个很久了。谢谢!【参考方案3】:我认为这种不当行为是因为您试图将少数内置/保留的事件名称“消息”之一用作特定于应用程序的消息。要确认,请将您的事件名称更改为“message2”或其他名称,然后查看问题是否消失。我相信至少保留了“连接”、“断开连接”和“消息”。 https://github.com/LearnBoost/socket.io/wiki/Exposed-events
【讨论】:
【参考方案4】:重新启动服务器可以负责客户端上的几个相同的事件侦听器。如果客户端尚未重新加载(重新启动),则必须确保在建立新连接时在客户端删除旧的事件侦听器。你可以用
io.socket.removeAllListeners()
【讨论】:
【参考方案5】:SOCKET.IO v3.x
我真的不知道为什么 socket.io 中的保留事件会多次触发,因此我制定了一个符合我们需求的逻辑并解决了这个问题,
我只是创建了一个全局可变值,每次“断开”启动时它都会改变,这是我所做的逻辑
let ACTIVE_USERS = []; //assume the propery of an object is name, socket_id
const connections = (socket) =>
socket.on("disconnect", (reason) =>
//lets check how many times it fires up
console.log('YOW', reason);
//mutate the ACTIVE_USERS
ACTIVE_USERS = ACTIVE_USERS .filter(user =>
//lets figure it out if this thing helps us
if(user.socket_id === socket.id)
console.log('HEY!!!');
socket.broadcast.emit('disconnected-user',[
message: `$user.name has been disconnected`
)
)
);
结果就在这里
【讨论】:
【参考方案6】:链接:https://socket.io/docs/v3/listening-to-events/#socketoffeventname-listener
请使用 socket.off 方法从名为eventName
的事件的侦听器数组中删除指定的侦听器。
socket.off("message").on("message", this.UpdateChat);
【讨论】:
虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。以上是关于Socket.io 消息事件多次触发的主要内容,如果未能解决你的问题,请参考以下文章
socket.io 监听器在功能性 React 中触发太多次