Node.js中如何将Pusher实例传递给工具类
Node.js跨模块传递初始化实例的实现方案
这个问题本质是Node.js项目中跨模块共享初始化后第三方实例的通用依赖传递问题,和Pusher本身没有绑定关系,以下是几种可直接落地的实现方式:
方案1:抽离Pusher实例为独立配置模块(最推荐,无耦合)
不要把Pusher的初始化逻辑写在server.js里,单独新建一个配置文件统一初始化,所有需要用到Pusher实例的地方直接引入这个配置文件即可,从根源避免传参问题。
- 新建
config/pusher.js配置文件:
import Pusher from 'pusher' // 统一在这里初始化Pusher实例 const pusher = new Pusher({ appId: "ddsd", key: "afdafa", secret: "asdfasdfasfadsf", cluster: "mt1", useTLS: true }); export default pusher;
- 修改
server.js,直接引入已经初始化好的pusher实例:
import express from 'express'; import cors from 'cors'; import bodyParser from 'body-parser' // 引入已经初始化好的pusher实例 import pusher from './config/pusher.js' const PORT = 4001; const app = express(); app.use(cors()); app.use(bodyParser.urlencoded({extended: false})); app.use(bodyParser.json()); app.post("/pusher/user-auth", (req, res) => { const socketId = req.body.socket_id; const user = {id: '12345'}; const authResponse = pusher.authenticateUser(socketId, user); res.send(authResponse); }); app.listen(PORT, () => { console.log(`Server running on port ${PORT}`) })
- 修改
controllers/messagesWebsocketController.js,同样引入pusher实例直接使用即可,不需要额外传参:
// 引入统一初始化的pusher实例 import pusher from '../config/pusher.js' class MessagesWebsocketController { async sendMessageToClients (message) { pusher.sendToUser("12345", "my-event1", { message}); } } const messagesWebsocketController = new MessagesWebsocketController(); export default messagesWebsocketController;
这种方式的优势是所有用到Pusher的地方都从同一个入口取实例,不会出现重复初始化的问题,也不需要在各个业务模块之间来回传参,维护成本最低。
方案2:控制器增加注入方法,在server.js完成依赖注入
如果不想抽离配置文件,也可以给控制器增加一个接收pusher实例的初始化方法,在server.js初始化完pusher之后把实例注入进去。
- 修改
controllers/messagesWebsocketController.js:
class MessagesWebsocketController { constructor() { this.pusher = null; } // 新增初始化方法,接收传入的pusher实例 init(pusherInstance) { this.pusher = pusherInstance; } async sendMessageToClients (message) { if (!this.pusher) throw new Error('Pusher instance not initialized, please call init method first'); this.pusher.sendToUser("12345", "my-event1", { message}); } } const messagesWebsocketController = new MessagesWebsocketController(); export default messagesWebsocketController;
- 在
server.js中初始化完pusher之后,调用控制器的init方法注入实例:
import messagesWebsocketController from './controllers/messagesWebsocketController.js' // 之前的pusher初始化逻辑不变 const pusher = new Pusher({/* 你的配置 */}); // 注入pusher实例到控制器 messagesWebsocketController.init(pusher);
这种方式符合依赖注入的设计思路,后续如果要替换成其他websocket实现,只需要修改注入的实例即可,不需要改控制器内部逻辑。注意要在服务启动、所有接口注册之前完成注入,避免调用方法时实例还没赋值。
方案3:不要提前导出单例,使用时再传参初始化
如果不想用全局单例,也可以修改控制器的导出方式,不在文件里直接实例化,而是在server.js里实例化的时候传入pusher参数。
- 修改
controllers/messagesWebsocketController.js,只导出类,不提前实例化:
export default class MessagesWebsocketController { // 构造函数接收pusher实例 constructor(pusher) { this.pusher = pusher; } async sendMessageToClients (message) { this.pusher.sendToUser("12345", "my-event1", { message}); } }
- 在
server.js中初始化完pusher之后,再实例化控制器:
import MessagesWebsocketController from './controllers/messagesWebsocketController.js' const pusher = new Pusher({/* 你的配置 */}); // 实例化控制器的时候传入pusher const messagesWebsocketController = new MessagesWebsocketController(pusher);
如果其他模块需要用到这个控制器实例,可以把实例挂载到app上下文,或者再单独导出实例即可。
注意:你提供的原始控制器代码存在语法错误,
class messagesWebsocketController()后面多了括号,类定义不需要跟括号,括号是实例化时才使用的语法,同时类名建议遵循大驼峰命名规范,否则实例化时会直接报错。
内容的提问来源于stack exchange,提问作者william007
相关产品推荐
相关产品推荐

