因为我从angular2开始,我设置了我的服务来返回T的Observable.在服务中,我会调用map(),使用这些服务的组件只会使用subscribe()来等待响应.对于这些简单的场景,我真的不需要深入研究rxjs,所以一切都很好.
我现在希望实现以下目标:我正在使用带刷新令牌的OAuth2身份验证.我想构建一个所有其他服务都将使用的API服务,该服务将在返回401错误时透明地处理刷新令牌.因此,在401的情况下,我首先从OAuth2端点获取一个新令牌,然后使用新令牌重试我的请求.以下是运行良好的代码,并promise :
request(url: string, request: RequestOptionsArgs): Promise<Response> {
var me = this;
request.headers = request.headers || new Headers();
var isSecureCall: boolean = true; //url.toLowerCase().startsWith('https://');
if (isSecureCall === true) {
me.authService.setAuthorizationHeader(request.headers);
}
request.headers.append('Content-Type', 'application/json');
request.headers.append('Accept', 'application/json');
return this.http.request(url, request).toPromise()
.catch(initialError => {
if (initialError && initialError.status === 401 && isSecureCall === true) {
// token might be expired, try to refresh token.
return me.authService.refreshAuthentication().then((authenticationResult:AuthenticationResult) => {
if (authenticationResult.IsAuthenticated == true) {
// retry with new token
me.authService.setAuthorizationHeader(request.headers);
return this.http.request(url, request).toPromise();
}
return <any>Promise.reject(initialError);
});
}
else {
return <any>Promise.reject(initialError);
}
});
}
在上面的代码中,authService.refreshAuthentication()将获取新令牌并将其存储在localStorage中.授权服务.setAuthorizationHeader将"Authorization"头设置为以前更新的令牌.如果查看catch方法,您将看到它返回一个promise (对于刷新令牌),该promise 最终将返回另一个promise (对于请求的实际第二次try ).
我试图做到这一点,但没有诉诸promise :
request(url: string, request: RequestOptionsArgs): Observable<Response> {
var me = this;
request.headers = request.headers || new Headers();
var isSecureCall: boolean = true; //url.toLowerCase().startsWith('https://');
if (isSecureCall === true) {
me.authService.setAuthorizationHeader(request.headers);
}
request.headers.append('Content-Type', 'application/json');
request.headers.append('Accept', 'application/json');
return this.http.request(url, request)
.catch(initialError => {
if (initialError && initialError.status === 401 && isSecureCall === true) {
// token might be expired, try to refresh token
return me.authService.refreshAuthenticationObservable().map((authenticationResult:AuthenticationResult) => {
if (authenticationResult.IsAuthenticated == true) {
// retry with new token
me.authService.setAuthorizationHeader(request.headers);
return this.http.request(url, request);
}
return Observable.throw(initialError);
});
}
else {
return Observable.throw(initialError);
}
});
}
上面的代码并没有达到我预期的效果:在200响应的情况下,它会正确地返回响应.然而,如果它捕捉到401,它将成功地检索到新的令牌,但是subscribe将最终检索到一个可观察的而不是响应.我猜这是应该进行重试的未执行的可观察对象.
我意识到,将promise的工作方式翻译到rxjs库中可能不是最好的方式,但我还没能理解"一切都是流"这一点.我try 了其他一些解决方案,包括flatmap、retryWhen等...但没走多远,所以我们很感激你的帮助.