SubscribeMessage 装饰器不会触发事件“消息”

Tom*_*ing 4 typescript nestjs ws

我正在 NestJS 后端设置 WebSocket 服务器,当我尝试订阅默认的“消息”事件类型时,该方法handleMessage()不会被触发。

但是该listenForMessages()方法有效(在服务器初始化后触发)。有谁知道装饰器为什么@SubscribeMessage('message')不工作?

@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}`);
  }
}
Run Code Online (Sandbox Code Playgroud)

SPS*_*SPS 7

//@SubscribeMessage('message') will look for the message that are in the format :\n{\n  event:'message',\n  data: {someData} // Whatever in the data field will be the payload in \n                   //handleMessage()\n}\n\n// Another example \n// @SubscribeMessage('get_profile') will look for messages in the format : \n\n{\n  event:'get_profile',\n  data: {someData} // Whatever in the data field will be the payload in \n                   //handleMessage()\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

那么为什么@SubscribeMessage('message')需要这样的格式呢?好吧,为了利用 NestJS 的功能,例如拦截器、管道等。如果您为传入消息(事件)实现这样的格式,将来即使将库更改为 socket.io,也不必更改处理程序逻辑或 \xce\xbcWebsocket.js 或您自己的 websocket 实现。您只需要实现您自己的自定义 websocket 适配器。

\n

简而言之,即使底层技术发生变化,NestJS 也能确保您的代码表达相同的内容。

\n

直接 listenForMessages() 在服务器上附加一个侦听器。这是一种特定于库的方法,如果您决定将库更改为:例如,socket.io,则需要更改所有侦听器逻辑。

\n

ws.on('message', callback);,将记录套接字发送的任何内容(按照您在 中的代码listenForMessages()),忽略格式,即:您可以发送字符串、缓冲区、JSON 等。但@SubscribeMessage(<event>)它必须采用以下格式:

\n
{\nevent : <event>,\ndata : <any>, // Can be string, number, object, buffer, whatever you want\n}\n
Run Code Online (Sandbox Code Playgroud)\n

ws - 是连接到服务器上的套接字。

\n

  • 正如我之前所说,向网关发送数据时应该有一个格式。因此,您应该从前端发送字符串化版本: ```{event:'message',date:{sender:1,content:'hello'}}```。这将触发 ```@SubscribeMessage('message')``` 并且 ```payload``` 将是 ```{sender:1,content:'hello'}``` (2认同)