NestJS拦截器-处理.pipe()中的错误

时间:2020-07-22 15:44:37

标签: node.js promise rxjs nestjs

我想实现一个NestJS拦截器,该拦截器在命中请求处理程序之前创建并写入elasticSearch条目,并在处理程序完成后使用error / success-info更新该条目。为此,我正在使用:

@Injectable()
export class ElasticsearchInterceptor implements NestInterceptor {

constructor(private readonly elasticSearchService: ElasticsearchService) {}

async intercept(_context: ExecutionContext, next: CallHandler): Promise < Observable < any >> {
    const elasticSearchPayload = new ElasticsearchPayloadBuilder()
        .setOperation(...)
        .build();
    const elasticSearchEntry = await this.elasticSearchService.writeEntry(elasticSearchPayload);

    return next
    .handle()
    .pipe(
        catchError(err => {
            elasticSearchPayload.status = err.status;
            return throwError(err);
        }),
        tap(() => {
            elasticSearchPayload.status = 'success';
        }),
        finalize(() => {
            this.elasticSearchService.updateEntry(elasticSearchEntry.id, elasticSearchPayload));
        }));
}

只要updateEntry呼叫能够解决,就可以正常工作,但是如果失败,则会导致未处理的拒绝。我想确保错误已被捕获并抛出。我尝试使用{p>将updateEntry承诺转换为新的Observable

finalize(() => {
    return from(this.elasticSearchService.updateEntry(elasticSearchEntry.id, elasticSearchPayload))
    .pipe(
        catchError(err => throwError(err)));
}));

但这不能解决问题。如何防止未处理的拒绝并从updateEntry返回错误?

1 个答案:

答案 0 :(得分:1)

finalize将在 teardown阶段中简单地调用提供的回调(例如,在complete,来自源的error或来自消费者的unsubscribe之后) ,这就是为什么我认为这种方式不起作用。

话虽如此,这将是我的方法:

const main$ = return next
  .handle()
  .pipe(
    catchError(err => {
        elasticSearchPayload.status = err.status;
        return throwError(err);
    }),
    tap(() => {
        elasticSearchPayload.status = 'success';
    }),
  );
const elastic$ = from(this.elasticService/* ... */).pipe(
  // might want to ignore elements and receive only errors
  ignoreElements(),

  catchError(err => throwError(err)),
);

return concat(main$, elastic$)