10

我正在尝试学习 node 并开始使用 socket.io 创建 mashup 消息传输已经开始,但我遇到了一些麻烦。

消息事件被触发多次,导致单个消息多次出现在收件人的盒子上。我已将套接字路由到exports.chat并想知道这是否导致了问题?

缩小问题范围:消息触发的次数=客户端的连接顺序。也就是说,如果客户端第二次连接,他的消息将触发两次。客户端连接第三次。

这是代码片段:

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);
                }
            });
        });
};
4

6 回答 6

7

socket.io 代码的整个部分必须在 external.chat 函数之外。Socket IO 必须与 http/app 服务器绑定,你不应该在每个请求中处理它。

消息触发的次数 = 客户端的连接顺序

本质上发生的是,每次新请求到达时,您都在为消息注册一个事件处理程序,因此它被触发的次数与您访问聊天 URL 的次数一样多。

io.socket.on('message', function (data) {...})
于 2013-10-03T15:35:50.583 回答
5

所以我遇到了同样的问题。解决方案是在 socket.on('disconnect') 事件上关闭所有侦听器,这就是我的代码的样子 -

 socket.on('disconnect', function () {
                socket.removeAllListeners('send message');
                socket.removeAllListeners('disconnect');
                io.removeAllListeners('connection');
            });

可能不需要在断开连接时调用它,不确定但我还是这样做了。

于 2016-05-01T23:11:52.247 回答
2

我认为这种不当行为是因为您试图将少数内置/保留事件名称“消息”之一用作特定于应用程序的消息。要确认,请将您的事件名称更改为“message2”或其他名称,然后查看问题是否消失。我相信至少保留了“连接”、“断开连接”和“消息”。https://github.com/LearnBoost/socket.io/wiki/Exposed-events

于 2013-10-03T15:31:34.827 回答
0

重新启动服务器可以负责客户端上的几个相同的事件侦听器。如果客户端没有重新加载(重新启动),您必须确保在建立新连接时在客户端删除旧的事件侦听器。你可以这样做

io.socket.removeAllListeners()
于 2020-03-04T11:41:03.797 回答
0

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`
        })
      }
    })
  });
}

结果就在这里

在此处输入图像描述

于 2021-08-13T18:06:47.840 回答
0

链接:https ://socket.io/docs/v3/listening-to-events/#socketoffeventname-listener

请使用 socket.off 方法从名为 的事件的侦听器数组中删除指定的侦听器eventName

socket.off("message").on("message", this.UpdateChat);

在此处输入图像描述

于 2021-12-25T13:19:27.093 回答