如何在NestJS同模块服务中访问WebSocketGateway的Server实例?
在NestJS同一模块的服务中访问WebSocketGateway的Server实例
问题场景
使用Socket.io的NestJS项目中,同一模块下的PaymentService需要调用PaymentGateway里由@WebSocketServer()修饰的Server实例执行emit操作,但尝试注入WebSocketAdapter失败,报错:
"Nest can't resolve dependencies of the [ServiceName] (?). Please make sure that the argument dependency at index [0] is available in the [Module] context."
相关代码片段:
PaymentGateway
@WebSocketGateway({ cors: true }) export class PaymentGateway { constructor(private readonly paymentService: PaymentService) {} @WebSocketServer() server: Server @SubscribeMessage('pay') @UsePipes(new WSValidationPipe()) create(@MessageBody() createPaymentDto: CreatePaymentDto, @ConnectedSocket() client: Socket ) { return this.paymentService.create(createPaymentDto, client) } }
PaymentService
@Injectable() export class PaymentService { constructor(private botService: BotService) {} async create(createPaymentDto: CreatePaymentDto, client: Socket) { // ... } async sendError(error: ILogError, socketId: string) { // this.server.emit('error', error.text) <--- 如何实现? } }
解决方案
方法一:直接注入WebSocketGateway到Service
由于PaymentGateway和PaymentService属于同一模块,Gateway本身是可注入的,直接在Service构造函数中注入Gateway即可访问其server属性:
修改PaymentService:
@Injectable() export class PaymentService { constructor( private botService: BotService, private readonly paymentGateway: PaymentGateway // 注入Gateway实例 ) {} async create(createPaymentDto: CreatePaymentDto, client: Socket) { // ... } async sendError(error: ILogError, socketId: string) { // 访问Gateway中的server实例执行emit this.paymentGateway.server.emit('error', error.text); // 若需给指定socket发送消息,可使用to方法 // this.paymentGateway.server.to(socketId).emit('error', error.text); } }
注意:确保PaymentGateway已在模块的providers数组中声明(NestJS通常会自动处理,手动配置模块时需确认)。
方法二:将Server实例注册为自定义提供者
若不想直接依赖Gateway,可将Server实例注册为独立的可注入token:
- 在模块文件中定义自定义token:
export const SOCKET_IO_SERVER = Symbol('SOCKET_IO_SERVER');
- 在
PaymentGateway中通过OnModuleInit钩子注册Server实例:
@WebSocketGateway({ cors: true }) export class PaymentGateway implements OnModuleInit { constructor( private readonly paymentService: PaymentService, private readonly moduleRef: ModuleRef // 注入ModuleRef ) {} @WebSocketServer() server: Server onModuleInit() { // 将Server实例注册到容器 this.moduleRef.register(SOCKET_IO_SERVER, this.server); } // ... 其他方法 }
- 在
PaymentService中注入该token对应的Server实例:
@Injectable() export class PaymentService { constructor( private botService: BotService, @Inject(SOCKET_IO_SERVER) private readonly server: Server // 注入Server实例 ) {} async sendError(error: ILogError, socketId: string) { this.server.emit('error', error.text); // 或指定socket发送 // this.server.to(socketId).emit('error', error.text); } }
内容的提问来源于stack exchange,提问作者WWCode
相关产品推荐
相关产品推荐

