简体   繁体   English

多次触发 Socket.io 消息事件

[英]Socket.io message event firing multiple times

I was trying to learn node and started creating a mashup with socket.io The message transportation have begin but I have run into some trouble.我正在尝试学习 node 并开始使用 socket.io 创建 mashup 消息传输已经开始,但我遇到了一些麻烦。

The message event is firing multiple times leading to a single message appearing multiple times on the recipient's box. message 事件多次触发,导致一条消息在收件人的框中多次出现。 I have routed the socket to exports.chat and was wondering if that is causing the problem?我已将套接字路由到exports.chat并想知道这是否导致了问题?

To narrow down the problem: the messages are firing the number of times = the sequence of connection of the client.缩小问题范围:消息触发的次数 = 客户端的连接顺序。 That is, if a client connects second, his messages will fire twice.也就是说,如果客户端第二次连接,他的消息将触发两次。 three times for the client connecting third.客户端连接第三次三次。

Here is the code snippet:这是代码片段:

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

The whole part of socket.io code has to go outside external.chat function. socket.io 代码的整个部分必须在 external.chat 函数之外。 Socket IO has to bind with the http/app server, you should not handle it within each request. Socket IO 必须与 http/app 服务器绑定,您不应该在每个请求中处理它。

the messages are firing the number of times = the sequence of connection of the client消息触发的次数 = 客户端的连接顺序

What essentially happening is, each time a new request arrives you are registering a event handler for message, hence it is fired as many times as the you have accessed chat URL.本质上发生的事情是,每次新请求到达时,您都在为消息注册一个事件处理程序,因此它被触发的次数与您访问聊天 URL 的次数一样多。

io.socket.on('message', function (data) {...})

So I had the same problem.所以我遇到了同样的问题。 The solution is to close all your listeners on the socket.on('disconnect') event, this is what my code looks like -解决方案是关闭 socket.on('disconnect') 事件上的所有侦听器,这就是我的代码的样子 -

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

Might not need to call it on disconnect, not sure but I do it anyway.可能不需要在断开连接时调用它,不确定但我还是这样做了。

I think this misbehavior is because you are attempting to use one of the handful of built-in/reserved event names "message" as an application-specific message.我认为这种不当行为是因为您试图将少数内置/保留事件名称“消息”之一用作特定于应用程序的消息。 To confirm, change your event name to "message2" or something else and see if the problem goes away.要确认,请将您的事件名称更改为“message2”或其他名称,然后查看问题是否消失。 I believe at least "connect", "disconnect", and "message" are reserved.我相信至少保留了“连接”、“断开连接”和“消息”。 https://github.com/LearnBoost/socket.io/wiki/Exposed-events https://github.com/LearnBoost/socket.io/wiki/Exposed-events

Restarting the server can be responsible for several identical event listeners on the client side.重新启动服务器可以负责客户端上的几个相同的事件侦听器。 If the client has not reloaded (restarted) you have to make sure that the old event listeners are deleted on the client side when establishing a new connection.如果客户端尚未重新加载(重新启动),则必须确保在建立新连接时在客户端删除旧的事件侦听器。 You can do that with你可以这样做

io.socket.removeAllListeners()

SOCKET.IO v3.x SOCKET.IO v3.x

I don't really know why reserve event in socket.io are firing up multiple times, hence I make a logic that fits to our needs and address this problem,我真的不知道为什么 socket.io 中的保留事件会多次触发,因此我制定了一个符合我们需求的逻辑并解决了这个问题,

I simply create a global mutable value that could change everytime the 'disconnect' fire up, here's the logic I did我只是创建了一个全局可变值,它可以在每次“断开连接”启动时改变,这是我所做的逻辑

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

and the result of it is here结果就在这里

在此处输入图片说明

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

Please use socket.off method to removes the specified listener from the listener array for the event named eventName .请使用 socket.off 方法从名为eventName的事件的侦听器数组中删除指定的侦听器。

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

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM