如何防止 Angular 中的拦截器重复请求?

How to prevent duplicated requests for interceptor in Angular?

我有一个 interceptor 拦截从 200 OK 消息收到的 401 错误代码。

不幸的是,我无法将 API 服务器修改为 return 401 错误而不是 200 OK 错误代码。

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
  switchMap((result: any) => {
    //401 unauthorized error message
    if (result && result.body && result.body.isSuccess == false && result.body.errorCode == '401') {
      return this.unAuthorizedError(request, next);
    } else {
      return next.handle(request);
    }
  }),
  catchError((error) => {
    if (error instanceof HttpErrorResponse) {
      switch ((<HttpErrorResponse>error).status) {
        case 401:
        case 403:
          return this.unAuthorizedError(request, next);
        default:
          break;
      }
    }
    return throwError(error);
  })
);
}

问题是每个请求都发送了两次,我认为这是 可能 由于 switchMap 方法 returns next.handle(request).

我试过 tap 方法

 tap((result: any) => {
    //401 unauthorized error message
    if (result && result.body && result.body.isSuccess == false && result.body.errorCode == '401') {
      return this.unAuthorizedError(request, next);
    }
  }),

它只发送一次请求,但是当令牌过期时 this.unAuthorizedError(request, next) 不会被调用。

我认为你是对的,next.handle(request);所做的就是再次提出请求。

创建 switchMap 的内部可观察对象时,您已经有了响应,所以我想说您可以将 next.handle() 替换为 of(response) 以便它可以被使用哪个部分发起了请求:

/* ... */
return next.handle(request).pipe(
  switchMap((result: any) => {
    //401 unauthorized error message
    if (result && result.body && result.body.isSuccess == false && result.body.errorCode == '401') {
      return this.unAuthorizedError(request, next);
    } else {
      return of(result);
    }
  }),
)
/* ... */

我写了一篇关于 Angular 的文章 HTTPClientModulehere's 我在其中谈论拦截器的部分。