【发布时间】:2017-08-04 05:50:33
【问题描述】:
我是使用 Angular 和 Rxjs 的新手。
基本上,应用使用 Api 并需要提供有效的身份验证令牌。 这个令牌是短暂的,如果它已经过期,它可以被刷新。
我编写了一个特定的 http 服务,它为每个请求添加正确的标头,并且在身份验证失败的情况下尝试刷新令牌并重试。
以下是我的实现方式:
export class HttpAService extends Http {
constructor(
backEnd: XHRBackend,
options: RequestOptions,
private authenticationService: AuthenticationService
) {
super(backEnd, options);
// get an authentication token from an authentication service
let token = authenticationService.token;
options.headers.set('Authorization', `Bearer ${token}`);
}
private request1(
url: string | Request,
options?: RequestOptionsArgs
): Observable<Response> {
// get a token from an authentication service
let token = this.authenticationService.token;
// add it to the request headers
if (typeof url === 'string') {
if (!options) {
options = { headers: new Headers };
}
options.headers.set('Authorization', `Bearer ${token}`);
} else {
url.headers.set('Authorization', `Bearer ${token}`);
}
// make the request
return super.request(url, options);
}
public request(
url: string | Request,
options?: RequestOptionsArgs
): Observable<Response> {
// init retry flag
let retried: boolean = false;
// make the request and retry one time in case of failure
const obs = Observable.defer(() => this.request1(url, options));
return obs.retryWhen(attempt => {
// request failed
return attempt.flatMap(res => {
// if it's the first round and an authentication error try to refresh token
if ((!retried) && (500 === res.status) && ('Unauthenticated.' == res.json().message)) {
retried = true;
// refresh attempts to create a new token that can be retrieved using authenticationService.getToken.
return this.authenticationService.refresh();
}
return Observable.throw(res);
})
})
}
}
我遇到的问题是让重试请求使用新令牌(换句话说,在重试期间让 request1 函数重新运行)。看来 defer(...) 成功了。
我想知道这个实现是否正确,是否有更优雅的方式来实现这个行为。
感谢您的回复。
【问题讨论】: