如何在app.js外部复用Socket.IO实例供控制器直接导入使用
Socket.IO跨文件复用解决方案
针对三层架构下Socket.IO实例重复初始化、无法跨文件调用的问题,通过单例模式抽离独立模块即可解决,实现一次初始化全项目复用:
1. 抽离独立Socket.IO单例模块
新建utils/socket.js文件,统一管理实例的初始化和获取逻辑,保证全局只有一个IO实例:
// utils/socket.js let ioInstance; module.exports = { // 服务启动时调用一次,完成实例初始化和全局事件绑定 init: (httpServer) => { const { Server } = require('socket.io'); ioInstance = new Server(httpServer, { cors: { origin: "*", // 按需修改跨域配置 methods: ["GET", "POST"] } }); // 全局命名空间、连接监听统一在这里绑定,不要散落在控制器中 ioInstance.of('/not').on("connection", (socket) => { console.log("/not namespace connected, socket id:", socket.id); // 这里可以统一写鉴权、通用事件监听逻辑 }); return ioInstance; }, // 业务层调用该方法获取已初始化的实例 getIO: () => { if (!ioInstance) throw new Error("Socket.IO未初始化,请先在服务入口执行init方法"); return ioInstance; } }
2. 服务入口统一初始化实例
在项目启动文件(app.js/bin/www等HTTP服务初始化位置),完成IO实例的一次性初始化:
const express = require('express'); const app = express(); const http = require('http'); // 基于express服务创建HTTP server,供Socket.IO挂载 const server = http.createServer(app); // 导入socket模块,执行全局初始化 const { init: initSocket } = require('./utils/socket'); initSocket(server); // 后续正常注册中间件、路由即可 const userRoutes = require('./routes/user'); app.use('/api/user', userRoutes); server.listen(3000, () => { console.log('服务启动在3000端口'); });
3. 控制器层直接导入调用
控制器中不需要重复初始化IO、重复绑定连接事件,直接引入getIO方法即可拿到实例使用。修正后的getAllUserConnections代码如下:
// 控制器文件顶部导入工具方法 const { getIO } = require('../utils/socket'); async getAllUserConnections (req,res){ const uid = req.user.id; try { const data = await db.userConnections.findAll({ where: { resiver_user_id: uid }, include: [{ model: db.user }] }); // 需要推送消息时直接获取实例调用即可 const io = getIO(); // 示例:向/not命名空间下的指定用户推送消息 // io.of('/not').to(`user_${uid}`).emit('connectionListUpdate', data); if (data.length === 0) return res.send('there is no Data to get'); return res.send(data); } catch(error) { return res.send(error); } }
关键注意事项
- 所有
connection事件监听、命名空间配置必须统一在init方法中绑定,绝对不要写在接口处理函数内,否则每次接口被请求都会重复绑定事件,引发内存泄漏、事件重复触发的问题。 - 必须保证Socket.IO初始化逻辑在路由注册、服务启动监听之前执行,避免业务层调用时实例还未创建。
内容的提问来源于stack exchange,提问作者Mouayad
相关产品推荐
相关产品推荐

