NestJS从ExceptionFilter抛出

时间:2019-03-01 13:44:53

标签: javascript node.js typescript exception-handling nestjs

我尝试使用ExceptionFilter将异常映射到其HTTP对应对象。

这是我的代码:

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

但是,当执行过滤器代码时,我得到了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)

我该如何解决?

4 个答案:

答案 0 :(得分:4)

这里的关键是扩展 const B = ({ itemsPerPage, totalItems }) => ( <nav> <ul className='pagination'> {[...new Array(Math.ceil(totalItems / itemsPerPage)).keys()].map(number => ( <li key={number} className='page-item'> {number} </li> ))} </ul> </nav> ); 并委托给超类而不是抛出:

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)); } } 参数,因为 applicationRef 需要此属性才能正确运行

BaseExceptionFilter

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

答案 1 :(得分:2)

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

或者,您可以创建一个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;
        }
      }));
  }
}

在此codesandbox中尝试一下。

答案 2 :(得分:1)

基于Kim Kern解决方案,我创建了这个抽象类

export abstract class AbstractErrorInterceptor<T> implements NestInterceptor {
    protected interceptedType: new (...args) => T;

    intercept(
        context: ExecutionContext,
        call$: Observable<any>,
    ): Observable<any> | Promise<Observable<any>> {
        return call$.pipe(
            catchError(exception => {
                if (exception instanceof this.interceptedType) {
                    this.handleError(exception);
                }
                throw exception;
            }),
        );
    }

    abstract handleError(exception: T);
}

以及一些实现

export class EntityNotFoundFilter extends AbstractErrorInterceptor<EntityNotFoundError> {
    interceptedType = EntityNotFoundError;

    handleError(exception: EntityNotFoundError) {
        throw new NotFoundException(exception.message);
    }
}

答案 3 :(得分:0)

您正在创建自己的版本的NestJS附带的基于HTTP的异常类,这很奇怪。默认情况下,这些将自动转换为带有正确错误代码的HTTP响应。您会增加Interceptor和抽象类实现的开销,而相反,您可以抛出NestJS错误并免费获取它。这是您所指的内置机制。

throw new BadRequestException('you done goofed');

导致:

{"statusCode":400,"error":"Bad Request","message":"you done goofed"}

Codesandbox (adapted from Kim's)