Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NestJS websocket Broadcast event to clients

I'm not able to send data from server NestJS to clients via websocket. Nothing is emitted.

My use case:

  • several clients connected to a server via websocket
  • client sends a message to the server via websocket
  • server broadcast the message to all client

My stack:

  • NestJS server with websocket
  • Angular client and other (like chrome extension for testing websockets)

My code:

simple-web-socket.gateway.ts:

import { SubscribeMessage, WebSocketGateway, WsResponse, WebSocketServer, OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit } from '@nestjs/websockets';

@WebSocketGateway({ port: 9995, transports: ['websocket'] })
export class SimpleWebSocketGateway implements OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit {

  @WebSocketServer() private server: any;
  wsClients=[];
  afterInit() {
    this.server.emit('testing', { do: 'stuff' });
  }

  handleConnection(client: any) {
    this.wsClients.push(client);
  }

  handleDisconnect(client) {
    for (let i = 0; i < this.wsClients.length; i++) {
      if (this.wsClients[i].id === client.id) {
        this.wsClients.splice(i, 1);
        break;
      }
    }
    this.broadcast('disconnect',{});
  }
  private broadcast(event, message: any) {
    const broadCastMessage = JSON.stringify(message);
    for (let c of this.wsClients) {
      c.emit(event, broadCastMessage);
    }
  }

  @SubscribeMessage('my-event')
  onChgEvent(client: any, payload: any) {
    this.broadcast('my-event',payload);
  }
}

main.ts:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { WsAdapter } from '@nestjs/websockets';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useWebSocketAdapter(new WsAdapter());
  await app.listen(3000);
}
bootstrap();

app.module.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { SimpleWebSocketGateway } from 'simple-web-socket/simple-web-socket.gateway';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService, SimpleWebSocketGateway],
})
export class AppModule {}

Additionnal Informations:

Client emiting (with code line c.emit(event, broadCastMessage);) return false.

I suspect an error in the framework as my usage is quite simple. But I want to double-check with the community here if I'm doing something wrong.

like image 836
user2650606 Avatar asked Dec 04 '18 09:12

user2650606


3 Answers

As mentionned in the previous comment, c.send() works fine with the following snippet:

import { SubscribeMessage, WebSocketGateway, WsResponse, WebSocketServer, OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit } from '@nestjs/websockets';

@WebSocketGateway({ port: 9995, transports: ['websocket'] })
export class SimpleWebSocketGateway implements OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit {

  @WebSocketServer() private server: any;
  wsClients=[];
  afterInit() {
    this.server.emit('testing', { do: 'stuff' });
  }

  handleConnection(client: any) {
    this.wsClients.push(client);
  }

  handleDisconnect(client) {
    for (let i = 0; i < this.wsClients.length; i++) {
      if (this.wsClients[i] === client) {
        this.wsClients.splice(i, 1);
        break;
      }
    }
    this.broadcast('disconnect',{});
  }
  private broadcast(event, message: any) {
    const broadCastMessage = JSON.stringify(message);
    for (let c of this.wsClients) {
      c.send(event, broadCastMessage);
    }
  }

  @SubscribeMessage('my-event')
  onChgEvent(client: any, payload: any) {
    this.broadcast('my-event',payload);
  }
}
like image 87
user2650606 Avatar answered Nov 20 '22 02:11

user2650606


I tried to broadcast a message to all connected clients using client.send():

broadcastMessage(event: string, payload: any) {
  for (const client of this.clients) {
    client.send(event, payload);
  }
}

testBroadcast() {
  this.broadcastMessage('msgInfo', { name: 'foo' });
}

the data sent ended up looking like this:

["message", "msgInfo", { "name": "foo" }]

The above did not work for me, so instead I used the client.emit() which works fine:

broadcastMessage(event: string, payload: any) {
  for (const client of this.clients) {
    client.emit(event, payload);
  }
}

now the data looks like this:

["msgInfo", { "name": "foo" }]
like image 3
Cyclonecode Avatar answered Nov 20 '22 03:11

Cyclonecode


With socket.io we could use socket.broadcast.emit()?:

@SubscribeMessage('my-event')
onChgEvent(
    @MessageBody() message: any,
    @ConnectedSocket() socket: Socket,
): void {
   socket.broadcast.emit('my-event', message);
}
like image 3
Philippe Avatar answered Nov 20 '22 02:11

Philippe