Как получить доступ к веб-сокету из контроллера или другого компонента / службы?

У меня есть 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.

Другие вопросы по тегам