Как получить доступ к веб-сокету из контроллера или другого компонента / службы?
У меня есть REST API, я хочу отправить событие клиенту через websocket. Как внедрить экземпляр websocket в контроллер или другой компонент?
3 ответа
Лучшее решение - создать глобальный модуль. Затем вы можете отправлять события из любого другого модуля / контроллера. A. Подход Afir создаст несколько экземпляров шлюза, если вы попытаетесь использовать его в других модулях.
Примечание: это простейшее решение.
Создайте socket.module.ts
import { Module, Global } from '@nestjs/common';
import { SocketService } from './socket.service';
@Global()
@Module({
controllers: [],
providers: [SocketService],
exports: [SocketService],
})
export class SocketModule {}
socket.service.ts
import { Injectable } from '@nestjs/common';
import { Server } from 'socket.io';
@Injectable()
export class SocketService {
public socket: Server = null;
}
app.gateway.ts
видеть afterInit
функция
import { WebSocketGateway, OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect, WebSocketServer } from '@nestjs/websockets';
import { Logger } from '@nestjs/common';
import { Server, Socket } from 'socket.io';
import { SocketService } from './socket/socket.service';
@WebSocketGateway()
export class AppGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
constructor(private socketService: SocketService){
}
@WebSocketServer() public server: Server;
private logger: Logger = new Logger('AppGateway');
afterInit(server: Server) {
this.socketService.socket = server;
}
handleDisconnect(client: Socket) {
this.logger.log(`Client disconnected: ${client.id}`);
}
handleConnection(client: Socket, ...args: any[]) {
this.logger.log(`Client connected: ${client.id}`);
}
}
Затем импортируйте SocketModule
в AppModule, и вы можете использовать Socket service
везде.
учебный класс Gateway
можно внедрить в другой компонент и использовать экземпляр сервера.
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
private readonly messageGateway: MessageGateway
) {}
@Get()
async getHello() {
this.messageGateway.server.emit('messages', 'Hello from REST API');
return this.appService.getHello();
}
}
Я полагаю, что @Raold пропустил факт в документации :
Шлюзы не должны использовать провайдеров на уровне запроса, потому что они должны действовать как синглтоны. Каждый шлюз инкапсулирует реальный сокет и не может быть создан несколько раз.
Таким образом, это означает, что мы не можем ни создавать экземпляр класса шлюза несколько раз, ни делать это явно с использованием функций областей внедрения.
Таким образом, создание только одного шлюза для одного пространства имен будет правильным, и он создаст только один экземпляр сервера websocket или socket.io.