Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 如何限制HTTP调用直到上一个调用完成_Angular_Rxjs5_Angular2 Observables - Fatal编程技术网

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得到一个