如何发送适配器@nestjs/platform-ws的nestjs websocket的异常/错误

问题描述 投票:0回答:4

我尝试根据条件使用nestjs websocket发送异常,尝试使用

抛出 new WsException('无效数据');

但不发送任何异常

这是示例代码

import WebSocket from 'ws';
import {
  SubscribeMessage,
  WebSocketGateway,
  WsException,
} from '@nestjs/websockets';

@WebSocketGateway({ path: '/api' })
export class MainGateway {
  @SubscribeMessage('message')
  handleMessage(client: WebSocket, payload: any) {
    if (payload.id === 4) {
      throw new WsException('Invalid Data');
    }
    client.send(JSON.stringify({ id: payload.id }));
  }
}

我正在使用 Angular 创建连接,这里是代码片段

export class WsComponent implements OnInit {
  public value!: number;
  public subject$ = webSocket('ws://localhost:3000/api');

  ngOnInit(): void {
    const event = { event: 'message', data: { id: 4 } };

    this.subject$.subscribe({
      next: (v: any) => (this.value = v.id),
      error: (e) => console.error(e),
      complete: () => console.info('complete'),
    });

    this.subject$.next(event);
  }
}

请帮我解决问题

javascript angular websocket rxjs nestjs
4个回答
4
投票

我也曾遇到同样的问题。我相信问题在于 BaseWsExceptionFilter 及其对 soket.emit 的使用。我想出了以下几点:

import { ArgumentsHost, Catch, HttpException } from "@nestjs/common";
import { BaseWsExceptionFilter, WsException } from "@nestjs/websockets";

@Catch(WsException, HttpException)
export class WebsocketExceptionsFilter extends BaseWsExceptionFilter {
  catch(exception: WsException | HttpException, host: ArgumentsHost) {
    const client = host.switchToWs().getClient() as WebSocket;
    const data = host.switchToWs().getData();
    const error = exception instanceof WsException ? exception.getError() : exception.getResponse();
    const details = error instanceof Object ? { ...error } : { message: error };
    client.send(JSON.stringify({
      event: "error",
      data: {
        id: (client as any).id,
        rid: data.rid,
        ...details
      }
    }));
  }
}

非常肯定

extends BaseWsExceptionFilter
是多余的,因为我没有使用该类的任何内容。然后我将其应用到我的网关:

@WebSocketGateway()
@UseFilters(WebsocketExceptionsFilter)
@UsePipes(new ValidationPipe({ transform: true }))
export class FeedGateway implements OnGatewayConnection, OnGatewayDisconnect {
}

这帮助我收到以下错误:

{"event":"error","data":{"id":"7a784ce568767a1016090c6a","rid":"connect","statusCode":400,"message":["language must be a valid enum value"],"error":"Bad Request"}}

3
投票

它正在工作,但需要更多测试。如果您发现错误,请报告。

import { ArgumentsHost, Catch } from '@nestjs/common';
import { BaseWsExceptionFilter } from '@nestjs/websockets';
import { PacketType } from 'socket.io-parser';
@Catch()
export class AllExceptionsSocketFilter extends BaseWsExceptionFilter {
   catch(exception: any, host: ArgumentsHost) {
      const client = host.switchToWs().getClient();
      client.packet({
          type: PacketType.ACK,
          data: [{ error: exception?.message }],
          id: client.nsp._ids++,
      });
   }
}

用途:

@WebSocketGateway()
@UseFilters(new AllExceptionsSocketFilter())
export class ContatoGateway {
   ...

编辑:新方法,正在运行并经过测试:

import { ArgumentsHost, Catch } from '@nestjs/common';
import { BaseWsExceptionFilter } from '@nestjs/websockets';

@Catch()
export class AllExceptionsSocketFilter extends BaseWsExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
  const args = host.getArgs();
  // event ack callback
  if ('function' === typeof args[args.length - 1]) {
    const ACKCallback = args.pop();
    ACKCallback({ error: exception.message, exception });
  }
}

}


2
投票

@WilyWork 更新的评论是正确的,但我发现在我的例子中,该函数不是最后一个参数。

我决定提出这个简单的函数。它应该可以完成这项工作,直到出现更强大的解决方案。

... in WsException filter
const args = host.getArgs();

        // Find possible acknowledgement callback from the end of arguments
        const ackCallback = this.findAckCallback(args);

        if (ackCallback !== null) {
            console.log("acknowledgement callback exists");
            ackCallback(wsEventErrorResponse);
        } else {
            console.log("acknowledgement callback does not exist");
            client.emit("globalError", wsEventErrorResponse);
        }
    }

    /**
     * Finds the acknowledgement callback from the end of the arguments.
     * @param args The arguments passed to the event handler.
     * @returns The acknowledgement callback if it exists, otherwise null.
     */
    private findAckCallback(args: unknown[]): Function | null {
        if (Array.isArray(args) && args.length >= 1) {
            for (let i = args.length - 1; i >= Math.max(0, args.length - 3); i--) {
                const arg = args[i];
                if (typeof arg === "function") {
                    return arg;
                }
            }
        }
        return null;
    }

0
投票

所有答案都不适合我。我必须打电话给

client.emit
,而不是
client.send
,才能让它正常工作:

在控制器中:

import { ArgumentsHost, Catch, HttpException } from '@nestjs/common';
import { WsException } from '@nestjs/websockets';

@Catch(WsException)
export class WsExceptionFilter {
  // Or any other exception.
  catch(exception: WsException, host: ArgumentsHost) {
    const client = host.switchToWs().getClient();
    client.emit('my-log-error-event', exception);
  }
}

在网关中:


@WebSocketGateway()
@UseFilters(new WsExceptionFilter())
export class ConnectionGateway {}
© www.soinside.com 2019 - 2024. All rights reserved.