I'm setting up a WebSocket server on my NestJS backend, and when I try subscribing on the default 'message' event type, the method handleMessage()
doesn't get triggered.
The listenForMessages()
method however works (which is triggered after the init of the server). Does anyone know why the decorator @SubscribeMessage('message')
doesn't work?
@WebSocketGateway()
export class AppWebsocketGateway implements OnGatewayInit, OnGatewayDisconnect {
private clientIds = new Map<string, string>();
// @ts-ignore
@WebSocketServer() server: Server;
private logger: Logger = new Logger('WebsocketGateway');
constructor(private readonly evseService: EvseService) {
}
listenForMessages() {
this.server.on('connection', (ws) => {
ws.on('message', (e) => {
console.log(e);
});
});
this.logger.log('message received');
}
@SubscribeMessage('message')
handleMessage(@ConnectedSocket() client: any, payload: any): void {
this.logger.log('I received a message from the client!');
this.server.emit('msgToClient', payload);
}
afterInit(server: Server) {
this.logger.log('Init');
this.listenForMessages();
}
handleDisconnect(@ConnectedSocket() client: any) {
this.logger.log(`Client disconnected: ${client.id}`);
}
}
//@SubscribeMessage('message') will look for the message that are in the format :
{
event:'message',
data: {someData} // Whatever in the data field will be the payload in
//handleMessage()
}
// Another example
// @SubscribeMessage('get_profile') will look for messages in the format :
{
event:'get_profile',
data: {someData} // Whatever in the data field will be the payload in
//handleMessage()
}
So why does @SubscribeMessage('message')
need such a format? Well, for leveraging NestJS features such as interceptors, pipes etc. If you implement such a format for the incoming messages (events), in the future, you would not have to change the handler logic even if you change the library to socket.io or μWebsocket.js or your own implementation for websockets. You just need to implement your own custom websocket adapter.
In short, NestJS makes sure that your code says the same even if the underlying technology changes.
The listenForMessages()
directly attaches a listener on the server. This is a library specific approach and you would need to change all the listener logic if you decide to change the library to: say, socket.io.
ws.on('message', callback);
, will log whatever the socket sends (as per your code in listenForMessages()
), disregarding the format,ie: you can send a string, buffer, JSON, etc.. but for @SubscribeMessage(<event>)
it has to be in the format :
{
event : <event>,
data : <any>, // Can be string, number, object, buffer, whatever you want
}
ws - is a socket which is connected on the server.