Cześć Mam ten oprogramowanie pośrednie do obsługi błędów w moim projekcie:

  private initializeErrorHandling() {
    this.app.use(
      (err: Error, request: Request, response: Response, _: NextFunction) => {
        if (err instanceof CustomExternalError) {
          return response.status(err.statusCode).json(err.message);
        }

        console.log(err);

        return response.status(500).json({
          status: 'error',
          message: 'Internal server error',
        });
      },
    );
  }

Używam następującej struktury kontrolera:

@singleton()
export class DepartamentController implements IController {
  private router: Router;
  private path: string;
  private services: DepartamentServices;
  constructor() {
    this.path = '/departament';
    this.router = Router();
    this.services = container.resolve(DepartamentServices);
    this.initializeRoutes();
  }
  private initializeRoutes() {
    this.router.post(`${this.path}/create`, this.test.bind(this));
  }
  getPath(): string {
    return this.path;
  }
  getRouter(): Router {
    return this.router;
  }

  private async test() {
    this.services.test();
  }

}

I to moja rola w mojej służbie, gdzie wywołam mój błąd:

 public async test() {
    throw new CustomExternalError(
      {
        message: 'Validation Failed',
        errors: [
          {
            resource: 'Departament',
            field: 'a',
            code: 'unprocessable',
          },
        ],
      },
      responseCodes.UNPROCESSABLE_ENTITY,
    );
  }

To jest mój niestandardowy błąd:

export class CustomExternalError {
  constructor(public error: responseError, public statusCode: responseCodes) {
    this.error;
    this.statusCode;
  }
}

I dodam moje trasy na mój ekspresowy serwer z następującą funkcją:

  private initializeRoutes() {
    container.resolveAll<IController>('Controller').forEach(controller => {
      this.app.use('/', controller.getRouter());
    });
  }

Moja trasa działa normalnie, ale z jakiegoś powodu podczas rzucania błędu nie nazywa mojego uchwytu błędu Middlware, ale jeśli zadzwonię o błędzie na moim kontrolera, działa normalnie

Mam ten błąd:

(node:8704) UnhandledPromiseRejectionWarning: #<CustomExternalError>
(Use `node --trace-warnings ...` to show where the warning was created)
(node:8704) 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(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:8704) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
0
Gabriel Costa 3 sierpień 2020, 14:33

1 odpowiedź

Najlepsza odpowiedź

Metoda test jest async, więc gdy rzuca wszystko, co trzeba być obsługiwane wewnątrz tej obietnicy {x1}} bloku, w przeciwnym razie będziesz mieć to obietnicę ostrzeżenie odrzucenia. Możesz więc utworzyć oprogramowanie pośrednie, które przyciągają te nieoblite obiecanie odrzucenia i przekazywania ich do oprogramowania pośredniczym obsługi błędów:

Możesz użyć metody opakowania, która obsługuje to:

const asynchHandler = fn => (...args) => fn(args).catch(args[2])

Lub ten pakiet: Express-Async-Handler.

Następnie w kontrolerze:

  private initializeRoutes() {
    this.router.post(`${this.path}/create`, asynchHandler(this.test.bind(this)));
  }

Lub po prostu poradzić sobie z obietnicą odrzuceniem i jawnie zadzwonić do midleware

private async test(request: Request, response: Response, next: NextFunction) {
  try {
     ...
     await this.service.test(...)
     ...
   } catch (err: CustomExternalError) {
     next(next)
   }
 }
1
Fcmam5 3 sierpień 2020, 13:17