最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - how to send the exceptionerror for nestjs websocket of adapter @nestjsplatform-ws - Stack Overflow

matteradmin4PV0评论

I am trying to send the exception using nestjs websocket based on conditions, tried using

throw new WsException('Invalid data');

but not sending any exception

Here is the sample code

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 }));
  }
}

and I'm creating the connection using angular here is the code snippet

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),
      plete: () => console.info('plete'),
    });

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

Please help me to solve the issue

I am trying to send the exception using nestjs websocket based on conditions, tried using

throw new WsException('Invalid data');

but not sending any exception

Here is the sample code

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 }));
  }
}

and I'm creating the connection using angular here is the code snippet

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),
      plete: () => console.info('plete'),
    });

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

Please help me to solve the issue

Share edited Jan 29, 2022 at 18:30 Sairam asked Jan 29, 2022 at 16:54 SairamSairam 632 silver badges6 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 4

I have struggled with same issue. I believe the issus is with BaseWsExceptionFilter and its usage of soket.emit. I've e up with following:

import { ArgumentsHost, Catch, HttpException } from "@nestjs/mon";
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
      }
    }));
  }
}

Pretty much sure extends BaseWsExceptionFilter is redundant as I did't use anything of that class. And then I applied it to my gateway:

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

This helped me to receive following error:

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

it's working but needs more testing. If you find a bug, please report it.

import { ArgumentsHost, Catch } from '@nestjs/mon';
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++,
      });
   }
}

Use:

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

EDIT: New method, working and tested:

import { ArgumentsHost, Catch } from '@nestjs/mon';
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 });
  }
}

}

The updated ment by @WilyWork is correct, but I found that in my case, the function is not the last argument.

I decided to e up with this simple function instead. It should do the job until a more robust solution es up.

... 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;
    }

None of the answers worked for me. I had to call client.emit, not client.send, to get it working:

In controller:

import { ArgumentsHost, Catch, HttpException } from '@nestjs/mon';
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);
  }
}

and in the gateway:


@WebSocketGateway()
@UseFilters(new WsExceptionFilter())
export class ConnectionGateway {}
Post a comment

comment list (0)

  1. No comments so far