typescript 在NestJS中,有没有什么方法可以使用异常过滤器来捕获来自服务的异常

yftpprvb  于 2023-04-22  发布在  TypeScript
关注(0)|答案(2)|浏览(173)

我已经创建了异常过滤器并全局注册了它,但是当我从服务文件中抛出一个HTTP异常时,异常过滤器不会捕获异常,但是当从控制器中抛出异常时,异常过滤器会正确地捕获异常。
例外过滤器:

import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
} from '@nestjs/common';
import { Response } from 'express';

@Catch(HttpException)
export class CommonFilter<T extends HttpException> implements ExceptionFilter {
  catch(exception: T, host: ArgumentsHost) {
    console.log('getting in common filter');
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}

注册为全局:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
import { CommonFilter } from './common/common.filter';
import {
  MongooseExeptions,
  MongooseValidationError,
} from './common/mongoose.filter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
      forbidNonWhitelisted: true,
      transform: true,
      transformOptions: {
        enableImplicitConversion: true,
      },
    }),
  );
  app.useGlobalFilters(
    new CommonFilter(),
    new MongooseExeptions(),
    new MongooseValidationError(),
  );

  await app.listen(3000);
}
bootstrap();

服务功能:

try {
  const pwdHash = hash(createUserDto.password, 5);
  const storeUser = await this.usersSchema.create({
    ...createUserDto,
    password: pwdHash,
  });
  if (storeUser) {
    const genrateOtp = new OTPGenrator().genrate(4);
    await this.UserOtpMailer.UserOtpMailer(
      storeUser.email,
      storeUser.name,
      genrateOtp,
    );
    return storeUser;
  }
  return;
} catch (error) {
  if (error instanceof Error.ValidationError) {
    throw new HttpException(
      error.message,
      HttpStatus.INTERNAL_SERVER_ERROR,
    );
  } else {
    throw new HttpException(
      error.message,
      HttpStatus.INTERNAL_SERVER_ERROR,
    );
  }
}

此服务将抛出mongoose验证错误,因为pwdHash不是字符串类型,如果是验证错误,我将抛出HTTP异常。
但是如果我从控制器抛出相同的错误,它会正常工作,但是不会捕获服务异常。

mbskvtky

mbskvtky1#

异常过滤器只会在控制器处理的请求的上下文中抛出错误时才捕获错误。这是因为异常过滤器是在应用程序级别注册的。
在控制器中执行以下操作:

async functionName() {
   try{
      ...
   } catch (error) {
      throw error;
   }
}

或者在控制器中使用@UseFilter(exceptionFilter)来处理服务抛出的异常,并在控制器中注册它

@Controller()
@UseFilters(MyExceptionFilter)
export class MyController {
   ...
}

@Injectable()
export class MyExceptionFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();

    if (exception instanceof HttpException) {
      response.status(exception.getStatus()).json({
        statusCode: exception.getStatus(),
        message: exception.message,
      });
    } else {
      response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
        statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
        message: 'Internal server error',
      });
    }
  }
}
lndjwyie

lndjwyie2#

我的代码中有一个错误,因为控制器无法捕获异常。我只需要将await从控制器放到服务函数中。
因此,我们不需要为nest做任何特殊的设置来捕获服务文件中的异常。

相关问题