首页 > 解决方案 > NestJS 拦截器 - 处理 .pipe() 内的错误

问题描述

我想实现一个 NestJS 拦截器,它在请求处理程序被命中之前创建并写入一个 elasticSearch 条目,并在处理程序完成后用错误/成功信息更新这个条目。为此,我正在使用:

@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-call 解决了,它就可以正常工作,但如果它失败,则会导致未处理的拒绝。我想确保错误被​​捕获并抛出。我尝试updateEntry使用将 -promise 转换为新的 Observable

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

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

标签: node.jspromiserxjsnestjs

解决方案


finalize将简单地在拆卸阶段(例如completeerror从源或消费者之后)调用提供的回调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$)

推荐阅读