简体   繁体   English

多个 Observables 共享单个 Error rxjs angular

[英]Multiple Observables sharing single Error rxjs angular

I am trying to handle API requests using Oauth2 authentication.我正在尝试使用 Oauth2 身份验证处理 API 请求。

I have an authService with three attributes ( accessToken , refreshToken & refreshTokenObservable – to be described later) and the apiGet() method which creates HTTP GET request with the Authorization header, like so:我有一个authService具有三个属性( accessTokenrefreshTokenrefreshTokenObservable - 稍后描述)和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)));
  }));
}

I want the handleApiGetError() method to call for a new refresh token and try to repeat the apiGet() , where I tried to connect multiple apiGet() calls to the single observable, like so:我希望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);
  }));
}

This, however, did not work as it called for the new token with every failed apiGet() , causing OAuth service to return multiple E401s (token was already revoked).但是,这不起作用,因为它在每个失败的apiGet()调用新令牌,导致 OAuth 服务返回多个 E401(令牌已被撤销)。

Is there any way to bind the apiGet() Observers together and in the case of error call the refresh token request only once with re-calling the failed apiGet() calls?有没有办法将apiGet()观察者绑定在一起,并且在错误的情况下只调用一次刷新令牌请求并重新调用失败的apiGet()调用?

Consider using retryWhen to retry only once, and most importantly to inverse the control, so that your ErrorHandler is not responsible for retrying again (by calling its caller).考虑使用retryWhen只重试一次,最重要的是反转控制,以便您的ErrorHandler不负责再次重试(通过调用其调用者)。
Using retryWhen your HTTP request will only be retried once the Observable returned by this.handleApiGetError() has been completed, as demonstrated below:使用retryWhen你的 HTTP 请求只会在this.handleApiGetError()返回的 Observable 完成后重试,如下所示:

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;
}

That being said, handleApiGetError might be unnecessary as you can instead call getAccessByRefreshToken directly, as following:话虽如此, handleApiGetError可能是不必要的,因为您可以直接调用getAccessByRefreshToken ,如下所示:

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

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

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