简体   繁体   English

如何在本地处理错误并跳过 Angular HTTP 拦截器?

[英]How can I handle an error locally and skip an Angular HTTP interceptor?

I have an Angular HttpInterceptor to catch errors and display appropriate, yet generic, error messages depending on the status code.我有一个 Angular HttpInterceptor来捕获错误并根据状态代码显示适当但通用的错误消息。

I have a specific case where I actually expect and error message (the UI tries to release a lock on a resource that has just been deleted, so I get 404).我有一个我实际期望的特定情况和错误消息(UI 尝试释放对刚刚被删除的资源的锁定,所以我得到 404)。

In that case I want to handle the error directly where I make the API call, and skip the interceptor.在这种情况下,我想直接在进行 API 调用的地方处理错误,并跳过拦截器。

I tried this:我试过这个:

releaseReviewerLock(itemType: EquipmentItemType, itemId: EquipmentItem["id"]): Observable<void> {
  return this.http
    .post<void>(`${this.configUrl}/${itemType.toLowerCase()}/${itemId}/release-reviewer-lock/`, {})
    .pipe(
      catchError(e => {
        if (e.status === HttpStatusCode.NotFound) {
          // We can ignore the 404 because the item has just been deleted, so there's nothing to release.
          return EMPTY;
        }
      })
    );
}

But not only is my intercepto called anyway, the catchError block above is not executed at all (breakpoint didn't stop).但不仅我的拦截器无论如何都被调用了,上面的catchError块根本没有执行(断点没有停止)。

Can I achieve what I want without modifying the interceptor and keeping a resemblance of single-responsibility?我可以在不修改拦截器并保持类似单一职责的情况下实现我想要的吗?

Thanks!谢谢!

We can pass some metadata context to HttpClient and then retrieve it inside the HttpInterceptor .我们可以将 一些元数据上下文传递给HttpClient ,然后在HttpInterceptor中检索它。

Of course, it implies to add some logic inside HttpInterceptor , but thanks to metadata context, this code could be more versatile, and stay simple.当然,这意味着在HttpInterceptor中添加一些逻辑,但是由于元数据上下文,这段代码可以更加通用,并且保持简单。

For example:例如:

In api.service.ts :api.service.ts

this.httpClient
  .get('http://...', {
    context: new HttpContext().set(IGNORED_STATUSES, [404]),
  })
  .pipe(
    catchError((e) => {
      console.log('Error catched locally', e);
      return of(EMPTY);
    })
  )
  .subscribe();

In error.interceptor.ts :error.interceptor.ts

export const IGNORED_STATUSES = new HttpContextToken<number[]>(() => []);

export class CustomHttpInterceptor implements HttpInterceptor {
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    const ignoredStatuses = req.context.get(IGNORED_STATUSES);

    return next.handle(req).pipe(
      catchError((e: HttpErrorResponse) => {

        // if ignored statuses are set
        // and returned status matched 
        if (ignoredStatuses?.includes(e.status)) {
          // rethrow error to be catched locally
          return throwError(() => e);
        }

        // process error...
        console.log('error interceptor !!', e);
        return of();
      })
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM