Angular 如何限制HTTP调用直到上一个调用完成
在我的Angular 如何限制HTTP调用直到上一个调用完成,angular,rxjs5,angular2-observables,Angular,Rxjs5,Angular2 Observables,在我的Angular 2应用程序中,我遇到了一个非常棘手的情况。在我的身份验证服务中,我有一个函数loggedIn,它从本地存储中读取jwt访问令牌,检查它是否过期,并用于控制路由。它在canActivate实现中调用: canActivate(....):Observable<boolean>{ return this.checkLogin(); } checkLogin():Observable<boolean>{ return this._auth
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);
}
从以下功能:
/*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;
}
刷新访问令牌的方法*/
refreshToken():可观察{
//安装材料
var res=this.http.post(url、数据、opts.map)(r=>data=r.json());
res.subscribe(数据=>{
localStorage['access_token']=data.access_token;
localStorage['refresh\u token']=data.refresh\u token;
设jwt=newjwthelper();
设t=jwt.decodeToken(localStorage['access_token']);
如果(t.Id){
this.Id=t.Id;
}
},error=>{console.log(error);
});
返回res;
}
但这导致了所有的麻烦。有无数的请求都失败了(因为第一个请求重置了刷新令牌
)
我想做的是,即使从
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;
}
isPendingSubject:BehaviorSubject=newbehaviorsubject(false);
isPending$:obserrable=this.isPendingSubject.asObservable();
/*方法刷新访问令牌*/
refreshToken():可观察{
//安装材料
const refreshingspending=this.isPendingSubject.value();
如果(this.refreshindispending)返回此.isPending$;
this.ispendinsubject.next(true);
this.refreshipPending=true;
var res=this.http.post(url、数据、opts.map)(r=>data=r.json());
res.subscribe(数据=>{
localStorage['access_token']=data.access_token;
localStorage['refresh\u token']=data.refresh\u token;
设jwt=newjwthelper();
设t=jwt.decodeToken(localStorage['access_token']);
如果(t.Id){
this.Id=t.Id;
}
this.isPendingSubject.next(false);
},error=>{console.log(error);
});
返回res;
}
如果您不介意在类中存储当前请求的状态,这可能是一个可行的选择
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;
}
isPendingSubject:BehaviorSubject=newbehaviorsubject(false);
isPending$:obserrable=this.isPendingSubject.asObservable();
/*方法刷新访问令牌*/
refreshToken():可观察{
//安装材料
const refreshingspending=this.isPendingSubject.value();
如果(this.refreshindispending)返回此.isPending$;
this.ispendinsubject.next(true);
this.refreshipPending=true;
var res=this.http.post(url、数据、opts.map)(r=>data=r.json());
res.subscribe(数据=>{
localStorage['access_token']=data.access_token;
localStorage['refresh\u token']=data.refresh\u token;
设jwt=newjwthelper();
设t=jwt.decodeToken(localStorage['access_token']);
如果(t.Id){
this.Id=t.Id;
}
this.isPendingSubject.next(false);
},error=>{console.log(error);
});
返回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$;
}
私有刷新$:可观察;
refreshToken():可观察{
如果(!this.refresh$){
this.refresh$=this.http.post(url、数据、选项)
.map(r=>data=r.json())
.share();
此.refresh$.subscribe(…);
}
返回此。刷新$;
}
很明显,我没有测试它,但我希望你明白我的意思。当您多次调用该方法时,始终会收到相同的可观察值和
share()
操作符确保每次只有一个活动的HTTP请求。因为您的问题基本上是在多个订阅者之间共享一个订阅,所以您可以在属性中保留可观察的内容,只需使用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$;
}
私有刷新$:可观察;
refreshToken():可观察{
如果(!this.refresh$){
this.refresh$=this.http.post(url、数据、选项)
.map(r=>data=r.json())
.share();
此.refresh$.subscribe(…);
}
返回此。刷新$;
}
很明显,我没有测试它,但我希望你明白我的意思。当您多次调用该方法时,您始终会收到相同的Observable,并且
share()
操作符确保此时始终只有一个活动的HTTP请求。是的,我考虑过这个问题,甚至尝试过它,但由于我需要返回Observable
,以便在整个链中使用,它改变了简单的return
不起作用的事情。我不知道你的意思。您正在对返回的订阅进行处理吗?是的,它最终用于CanActivate
。好的,我做了一些更改,以确保返回一个可观察的订阅。这有用吗,或者我走错了路了吗?是的,我考虑过这个问题,甚至尝试过,但由于我需要返回可观察的
以在链上消费,它改变了简单的返回
将不起作用的事情。我不确定你的意思。您正在对返回的订阅进行处理吗?是的,它最终用于CanActivate
。好的,我做了一些更改,以确保返回一个可观察的订阅。这有用吗,还是我走错了路?不。。。我在那里分享了,
,但仍然收到了无数的请求!让我用refresh$
@TheVillageIdiot再试一次,然后你做错了:)也许吧。但是如果没有类型参数
,则不允许使用可观察的
。如果它被设置为可观察的
subscribe得到一个