I have a REST API, I want to send event to the client via websocket. How to inject websocket instance in controller or another component?
3 Answers
Better solution is to create global module. You can then emit events from any other module/controller. A. Afir approach will create multiple instances of Gateway if you try to use it in other modules.
Note: This is just simplest solution
Create 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
see afterInit
function
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}`);
}
}
Then import SocketModule
into AppModule and you can use Socket service
everywhere.

- 6,669
- 1
- 29
- 54

- 1,383
- 4
- 20
- 33
-
1(I think this should be the accepted answer) - Thanks, it really helped me. Before doing so, each new client connecting was logged more than once, probably due to the multiple instances created in each module import. – Guilherme Abacherli Dec 25 '21 at 20:55
-
Also worked for me, thanks – IMalaniak Feb 08 '22 at 16:59
class Gateway
can be injected in another component, and use the server instance.
@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();
}
}
-
1Welcome to Stackoverflow! :-) Instead of writing [solved] in your answer text, consider accepting your answer. You may do so after 48h. See https://stackoverflow.com/help/accepted-answer – Kim Kern Jan 18 '19 at 03:23
-
if you want to send an event to a particular cline t using this approach how do you do that?. https://stackoverflow.com/questions/71349200/how-to-pass-socket-client-connection-from-nestjs-service – NicoleZ Mar 05 '22 at 04:05
I suppose that @Raold missed a fact in the documentation:
Gateways should not use request-scoped providers because they must act as singletons. Each gateway encapsulates a real socket and cannot be instantiated multiple times.
So it means that we can neither instantiate the gateway class multiple times nor do it explicitly using injection scopes features.
So creating just only one gateway for one namespaces will be right and it will produce only one instance of the websocket or socket.io server.

- 356
- 4
- 9
-
5Thanks for the feedback. I offered better solution for a specific case that works. I don't think this quote is directly related to my example. It would be better if you could explain why this is fundamentally wrong and offer some example. – Raold Jun 23 '21 at 16:56