首页 > 解决方案 > 如何从返回 observable 的函数订阅 observable?

问题描述

所以我有一个返回 observable 的 put 方法,在这个方法中我需要检查令牌是否有效,如果它无效,那么我需要调用另一个可以创建新刷新令牌的方法,我需要订阅到这个方法,这样我就可以更新本地刷新令牌的值,然后返回 put 方法的可观察对象。

这是我到目前为止所拥有的:

    public putRequest(endpoint: string, body: any):
     Observable < APIResponseModel < any >> {
      if (this.authService.isValidToken()) {
       //     . . .
      }));
    }
    else {

     // get a new token 
     const refresh = this.authService.refreshToken();

     return refresh.switchMap(response => {

      this.authService.setRefreshToken(response.results.refreshToken);

      return this.httpClient.put < any > (`${endpoint}`, body).pipe(map(result => {
       this.hideLoader();
       return result;
      }));
     }).catch(err => {
      console.log("error occurred! " + err)
      this.authService.redirectToLogin();
      return this.getNullResponse();
     });

    }

AuthService 方法:

  isValidToken(): boolean {
        const token = this.getAuthToken();
        if (!token && this.firstload) {

          return true; }
        if (token && !this.firstload) {
          if (this.jwtHelper.isTokenExpired(token)) { 
            console.log("Token is expired  ");

            return false;
          } else {
            return true;
          }
        } else {
          return false;
        }
      }

  refreshToken(): Observable<APIResponseModel<any>> {

    console.log("refresh token:" + this.getRefreshToken());
    const url = `${environment.baseAPIUrl}/${environment.version}/login/token/refresh`;
    const body = {
      refreshToken: `${this.getRefreshToken()}`
    };
    return this.httpClient.post(url, body).map((response: APIResponseModel<any>) => {
      this.setAuthToken(response.results.token);
      this.setRefreshToken(response.results.refreshToken);
      this.tokenBeingRefreshed = false;
      return response;
    }, err => err);
  }

请注意,我尝试了 SwitchMap 和 MergeMap,但我收到会话已过期的服务器错误。似乎我在等待生成新令牌之前收到此错误。如何确保在调用 httpClient.put 之前创建了新令牌?

标签: angulartypescriptrxjsobservableswitchmap

解决方案


因此,如果我正确地解决了您的问题,那就是

  • if (!token) → GET(token)
  • 重试 PUT

在这种情况下,正确的流程是

getData() {
  return this.http.put(...);
}

getToken() {
  return this.http.get(...);
}

isValidToken() {
  return ...;
}

securedCall() {
  const data$ = this.isValidToken ? 
    this.getData() : 
    this.getToken().pipe(
      switchMap(token => this.getData())
    );

  return data$;
}

比使用运算符更干净、更易于阅读!


推荐阅读