我的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
多次触发该功能,也只发出一个请求。有可能吗?
答案 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请求。