首页 > 解决方案 > 多个 Observables 共享单个 Error rxjs angular

问题描述

我正在尝试使用 Oauth2 身份验证处理 API 请求。

我有一个authService具有三个属性(accessToken, refreshToken& refreshTokenObservable– 稍后描述)和apiGet()使用 Authorization 标头创建 HTTP GET 请求的方法,如下所示:

apiGet(cleanedPath:string) {
  return this.config.getConfig().pipe(mergeMap((config: Config) => {
    
    [...] // Cleans parameters and creates a final query string

    // Adding access token as header
    let headers: object = {headers: new HttpHeaders().set('Authorization', this.accessToken)}

    return this.http.get<any>(cleanedPath, headers).pipe(catchError(this.handleApiGetError.bind(this, cleanedPath)));
  }));
}

我希望该handleApiGetError()方法调用新的刷新令牌并尝试重复apiGet(),我尝试将多个apiGet()调用连接到单个可观察对象,如下所示:

private handleApiGetError(cleanedPath:string, error: HttpErrorResponse) {
  if (!this.refreshTokenObservable) {
    // getAccessByRefreshToken() is simple HTTP post
    this.refreshTokenObservable = this.getAccessByRefreshToken();
  }
  return this.refreshTokenObservable.pipe(mergeMap(()=> {
    return this.apiGet(cleanedPath);
  }));
}

然而,这并没有奏效,因为它在每次失败时都需要新的令牌apiGet(),导致 OAuth 服务返回多个 E401(令牌已经被撤销)。

有没有办法将apiGet()观察者绑定在一起,并且在错误的情况下只调用一次刷新令牌请求并重新调用失败的apiGet()调用?

标签: angularrxjsobservable

解决方案


考虑使用retryWhento 仅重试一次,最重要的是反转控件,以便您ErrorHandler不负责再次重试(通过调用其调用者)。只有在完成返回的 Observable 后,才会重试
使用您的 HTTP 请求,如下所示:retryWhenthis.handleApiGetError()

apiGet(cleanedPath: string) {
  return this.config.getConfig().pipe(
    mergeMap((config: Config) => {
      return this.http.get<any>(cleanedPath, headers).pipe(
        retryWhen(x => this.handleApiGetError())
      );
    })
  );
}

private handleApiGetError(error: HttpErrorResponse) {
  return this.refreshTokenObservable;
}

话虽如此,handleApiGetError可能没有必要,因为您可以getAccessByRefreshToken直接调用,如下所示:

 apiGet(cleanedPath: string) {
   return this.config.getConfig().pipe(
     mergeMap((config: Config) => {
       return this.http.get<any>(cleanedPath, headers).pipe(
         retryWhen(this.getAccessByRefreshToken)
       );
     })
   );
 }

推荐阅读