我在我的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
多次触发只有一个请求。是否有可能以任何方式?
如果你不介意存储类当前请求的状态,这可能是一个可行的选择。
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;
}
由于您的问题基本上共享多个用户之间的一个订阅,你可以保持可观察的性质,只是使用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。