NestJS 从 ExceptionFilter 抛出

Var*_*kal 9 javascript exception-handling node.js typescript nestjs

我尝试使用 anExceptionFilter将异常映射到它们的 HTTP 对应项。

这是我的代码:

@Catch(EntityNotFoundError)
export class EntityNotFoundFilter implements ExceptionFilter {
    catch(exception: EntityNotFoundError, _host: ArgumentsHost) {
        throw new NotFoundException(exception.message);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当执行过滤器代码时,我得到了一个 UnhandledPromiseRejectionWarning

 (node:3065) UnhandledPromiseRejectionWarning: Error: [object Object]
    at EntityNotFoundFilter.catch ([...]/errors.ts:32:15)
    at ExceptionsHandler.invokeCustomFilters ([...]/node_modules/@nestjs/core/exceptions/exceptions-handler.js:49:26)
     at ExceptionsHandler.next ([...]/node_modules/@nestjs/core/exceptions/exceptions-handler.js:13:18)
     at [...]/node_modules/@nestjs/core/router/router-proxy.js:12:35
     at <anonymous>
     at process._tickCallback (internal/process/next_tick.js:182:7)
 (node:3065) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 5)
Run Code Online (Sandbox Code Playgroud)

我怎样才能解决这个问题 ?

Kim*_*ern 12

ExceptionFilter总是被调用送出响应之前,它负责构建响应最后的地方。您不能从ExceptionFilter.

@Catch(EntityNotFoundError)
export class EntityNotFoundFilter implements ExceptionFilter {
  catch(exception: EntityNotFoundError, host: ArgumentsHost) {
    const response = host.switchToHttp().getResponse();
      response.status(404).json({ message: exception.message });
  }
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以创建一个Interceptor来转换您的错误:

@Injectable()
export class NotFoundInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    // next.handle() is an Observable of the controller's result value
    return next.handle()
      .pipe(catchError(error => {
        if (error instanceof EntityNotFoundError) {
          throw new NotFoundException(error.message);
        } else {
          throw error;
        }
      }));
  }
}
Run Code Online (Sandbox Code Playgroud)

在这个codeandbox 中尝试一下。


Jem*_*nes 6

这里的关键是将BaseExceptionFilter和委托扩展到超类而不是抛出:

import { BaseExceptionFilter } from '@nestjs/core';
// .. your other imports

@Catch(EntityNotFoundError)
export class EntityNotFoundFilter extends BaseExceptionFilter {
    catch(exception: EntityNotFoundError, host: ArgumentsHost) {
        super.catch(new NotFoundException(exception.message, host));
    }
}
Run Code Online (Sandbox Code Playgroud)

applicationRef在应用程序引导期间构造过滤器时,请务必传入参数,因为BaseExceptionFilter需要此属性才能正确运行

import { HttpAdapterHost } from '@nestjs/core';
// .. your other imports

async function bootstrap(): Promise<void> {
  // .. blah blah
  const { httpAdapter } = app.get(HttpAdapterHost);
  app.useGlobalFilters(new GeneralErrorFilter(httpAdapter));
  // .. blah blah
}
Run Code Online (Sandbox Code Playgroud)

如果您抛出相同的错误,这将导致您将收到的默认错误处理。

  • 我真的很喜欢这个解决方案,因为它使用了 NestJS `NotFoundException`。但我建议谨慎转发“exception.message”。根据您的查询,您可能会暴露出超出您预期的信息。就我而言,我只是选择不提供更多细节。 (2认同)