制作要在任何文件中使用的 Socket io 单例类

Posted

技术标签:

【中文标题】制作要在任何文件中使用的 Socket io 单例类【英文标题】:Making a Socket io singleton class to be used in any file 【发布时间】:2021-12-28 03:28:48 【问题描述】:

我需要访问项目中多个文件中的io 模块,以便发出一些消息。所以为此我决定创建一个单例类来处理io 对象,这样我就可以在任何地方导入该类并使用io 对象。

当我注释掉所有中间件时,它就起作用了。但我不希望这样,我希望仅在用户登录时建立连接。

这是我的socketClass.js

const session = require('express-session');
const  Server  = require("socket.io");
const passport = require('passport');


class SocketManager
    constructor() 
        this.io = null;
    

    start(server) 
        this.io = new Server(server);

        // convert a connect middleware to a Socket.IO middleware
        const wrap = middleware => (socket, next) => middleware(socket.request, , next);

        const sessionMiddleware = session(
            secret: 'MySecrectKey',
            resave: true,
            saveUninitialized: true
        );
        this.io.use(wrap(sessionMiddleware));
        this.io.use(wrap(passport.initialize()));
        this.io.use(wrap(passport.session()));

        this.io.use((socket, next) => 
            if (socket.request.user) 
                next();
             else 
                next(new Error('unauthorized'))
            
        );
    

    get() 
        return this.io;
    



module.exports = new SocketManager();

这是我的app.js

...
const SocketManager = require('./socketClass');
const server = http.createServer(app);
SocketManager.start(server);
const io = SocketManager.get();

io.on('connect', async (socket) => 
    console.log(`new connection $socket.id`);
    socket.on('whoami', (cb) => 
        cb(socket.request.user ? socket.request.user.username : '');
    );
);

io.on('connect') 不会在新连接上控制台记录任何内容。这里有什么问题?

【问题讨论】:

它应该在您连接到客户端时打印。那么您的客户端是成功连接还是出现任何错误? 它不打印任何东西。我也没有收到任何错误。 你也可以分享你在客户端使用的代码吗?它会发出连接事件吗? 它甚至没有在服务器端进行控制台登录。不,它不会发出任何东西。 【参考方案1】:

您的问题可能是因为“async (socket)”。这是我尽可能简单的方法!

我创建了一个单独的文件(模块):

socket.js:

let io;

module.exports = 
  init: httpServer => 
    io = require('socket.io')(httpServer);
    return io;
  ,
  getIO: () => 
    if (!io) 
      throw new Error('Socket.io not initialized!');
    
    return io;
  
;

然后,在我的 app.js 中:

const app = express();
const server = app.listen(8080);
const io = require('./socket').init(server);
    io.on('connection', socket => 
      console.log('Client connected');
    );

【讨论】:

在哪里设置中间件? 哪个中间件? 看看我的start(server)函数。 应该在我的初始化函数中! 我在另一个 *** 问题上看到了这个解决方案并尝试了它,但它不适用于中间件。我已经更新了问题。

以上是关于制作要在任何文件中使用的 Socket io 单例类的主要内容,如果未能解决你的问题,请参考以下文章

iOS单例详解

iOS单例详解

我如何制作一个成员的实例并在任何地方使用它

需要将socket.io类更改为单例

Socket.IO 中的跨域连接

单例进程的跨平台代码?