如何限制HTTP调用,直到前一个完成

问题描述 投票:1回答:2

我在我的Angular 2应用一个非常棘手的局面。在我的身份验证服务,我有一个函数loggedIn从本地存储和读取支票JWT访问令牌是否过期或不并用于门的路线。这就是所谓的canActivate实现:

canActivate(....):Observable<boolean>{
    return this.checkLogin();
}

checkLogin():Observable<boolean>{
    return this._authSvc.isLoggedIn();
}

///AUTHSERVICE

isLoggedIn():Observable<boolean> {
    let ex = tokenNotExpired('access_token');
    if (ex) {
      let jwt = new JwtHelper();

      let t = jwt.decodeToken(localStorage['access_token']);
      if (t.Id) {
        this.Id = t.Id;
      }
    }
    return Observable.of(new Boolean()).map(x => ex);
}

最近,我实现了能力刷新在后端(ASP.Net Web API 2)令牌。现在,这个想法是刷新访问令牌如果使用刷新令牌过期。我试图从isLoggedIn方法下探它。如果访问令牌已过期,我将返回Observable<boolean>为:

if(ex){
}else{
    return this.refreshToken();//<---NEW OBSERVABLE
}

从下面的功能:

/*method to refresh the access token*/
refreshToken():Observable<boolean>{
    //setup stuff
    var res= this.http.post(url,data,opts).map(r=> data=r.json());

    res.subscribe(data=>{
        localStorage['access_token'] = data.access_token;
        localStorage['refresh_token'] = data.refresh_token;
        let jwt = new JwtHelper();
        let t = jwt.decodeToken(localStorage['access_token']);
        if (t.Id) {
          this.Id = t.Id;
        }
    }, error=>{console.log(error);
    });

    return res;
}

但是,这是造成所有的地狱冲出重围。有无休止的要求,所有失败(如第一个复位refresh token)。

我想要做的就是让即使函数从canActivate多次触发只有一个请求。是否有可能以任何方式?

angular rxjs5 angular2-observables
2个回答
0
投票

如果你不介意存储类当前请求的状态,这可能是一个可行的选择。

isPendingSubject: BehaviorSubject<boolean> = new BehaviorSubject(false);
isPending$: Obserrvable<boolean> = this.isPendingSubject.asObservable();

/*method to refresh the access token*/
refreshToken():Obserrvable<boolean> {
    //setup stuff
    const refreshIsPending = this.isPendingSubject.value();
    if (this.refreshIsPending) return this.isPending$;
    this.isPendingSubject.next(true);
    this.refreshIsPending = true;
    var res = this.http.post(url,data,opts).map(r=> data=r.json());

    res.subscribe(data=>{
        localStorage['access_token'] = data.access_token;
        localStorage['refresh_token'] = data.refresh_token;
        let jwt = new JwtHelper();
        let t = jwt.decodeToken(localStorage['access_token']);
        if (t.Id) {
          this.Id = t.Id;
        }
        this.isPendingSubject.next(false);
    }, error=>{console.log(error);
  });
  return res;
}

0
投票

由于您的问题基本上共享多个用户之间的一个订阅,你可以保持可观察的性质,只是使用share()操作,以避免使多个this.http.post()电话。

private refresh$: Observable;

refreshToken(): Observable<boolean> {
    if (!this.refresh$) {
        this.refresh$ = this.http.post(url,data,opts)
            .map(r=> data=r.json())
            .share();

        this.refresh$.subscribe(...);
    }

    return this.refresh$;
}

我明明没有测试,但我希望你明白了吧。当你调用该方法多次,你总是收到相同的可观测和share()运营商可以确保总有当时只有一个活动的HTTP reqeust。

© www.soinside.com 2019 - 2024. All rights reserved.