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

时间:2017-04-07 04:54:07

标签: angular rxjs5 angular2-observables

我的Angular 2应用中有一个非常棘手的情况。在我的auth服务中,我有一个函数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多次触发该功能,也只发出一个请求。有可能吗?

2 个答案:

答案 0 :(得分:0)

如果您不介意在课堂上存储当前请求的状态,这可能是一个可行的选择。

<form name="table_1" id="table_1" class="table_1">
<table id="table_1" class="table_1" cellspacing='0' class="js-serial" border="2">
    <thead>
   <tr>
            <th width="50"><center>No.</center></th>
            <th width="100"><center>Tanggal</center></th>
            <th width="80"><center>No.Polisi</center></th>
            <th width="60"><center>Netto</center></th>

  </tr>

    </thead>
    <tbody>

  </tbody>
  </table>
  </form></div>
  <div id="kanan" class="btn btn-default">
  <form name="table_2" id="table_2" class="table_2">
<table id="table_2" class="table_2" cellspacing='0' class="js-serial" border="2">
    <thead>
   <tr>
            <th width="50"><center>No.</center></th>
            <th width="100"><center>Tanggal</center></th>
            <th width="80"><center>No.Polisi</center></th>
            <th width="60"><center>Netto</center></th>

  </tr>

    </thead>
    <tbody>

  </tbody>
  </table>
  </form></div>
  <table>
  <tr>
            <td width=482>Total Keseluruhan Netto :</td>
            <td width=30>
            <input type="text" id="total_netto" class="total_netto" type="text" name="total_netto" size="17"  readonly="readonly" /> </td>

  </tr>
  </table>

答案 1 :(得分:0)

由于您的问题基本上是在多个订阅者之间共享一个订阅,因此您可以将Observable保留在属性中,只需使用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$;
}

我显然没有测试它,但我希望你明白这一点。当您多次调用该方法时,您总是会收到相同的Observable,而share()运算符确保当时只有一个活动的HTTP请求。