socket.io 发出多次触发的事件

socket.io Emit events firing multiple times

我在这里阅读了一些关于这个主题的问题,但我还不确定如何解决我的问题。 getMsgs 发出事件的触发次数与我访问 /admin url 的次数一样多。我从 SO 上的其他问题知道这是因为每次我访问 admin 页面时听众都在注册,但我不确定如何重构我的代码(即移动 io.on(..) 和如何从 router.get('/admin'..) 函数中调用它。

router.get('/admin', function(req, res, next){
    io.on('connection', function (socket) {
        dal.findAllMessages(function(err, messages) {
            console.log('sent msgs');
            socket.emit('getMsgs', messages);
        });

        socket.on('newMsg', function(data){
            console.log('newMsg');
            console.log(data);
            dal.addMessage(data);
            dal.findAllMessages(function(err, messages) {
                socket.emit('getMsgs', messages);
            });
        });

        socket.on('delMsg', function(data){
            console.log('delMsg');
            console.log(data);
            dal.deleteMessage(data);
            dal.findAllMessages(function(err, messages) {
                socket.emit('getMsgs', messages);
            });
        });
    });
    res.render('admin');
});

io.on(...) 代码移到路线之外。每次命中 /admin 路由时,您都会重新注册一个新的事件处理程序,因此您会为完全相同的事件获得多个事件处理程序。

router.get('/admin', function(req, res, next){
    res.render('admin');
});

io.on('connection', function (socket) {
    dal.findAllMessages(function(err, messages) {
        console.log('sent msgs');
        socket.emit('getMsgs', messages);
    });

    socket.on('newMsg', function(data){
        console.log('newMsg');
        console.log(data);
        dal.addMessage(data);
        dal.findAllMessages(function(err, messages) {
            socket.emit('getMsgs', messages);
        });
    });

    socket.on('delMsg', function(data){
        console.log('delMsg');
        console.log(data);
        dal.deleteMessage(data);
        dal.findAllMessages(function(err, messages) {
            socket.emit('getMsgs', messages);
        });
    });
});

如果您不希望 socket.io 事件处理程序在它到达 /admin 路由之前被安装,那么您可以保留一个标志来确定它们是否已设置。

如果您只想将 socket.io 事件处理程序应用于特定的管理客户端,那么您将需要一种不同的方法,使用某种身份验证来决定是否允许 socket.io 连接连接与否。

尝试使用 socket.removeAllListeners()