我正在Angular 2中开发一个应用程序,其中在不同时间段进行了多个API调用。
当访问令牌已过期并且需要刷新时,就会出现问题。
对于每个API调用,我都会检查令牌状态。
当令牌过期时,将调用Access令牌API,之后将执行实际的API调用。
只有一个API调用时,此功能可以正常使用。
但是,如果令牌过期时有N个API调用,则访问令牌API也被调用N次。
这是当前流程,
postRequest(url, body, header): Observable<Object> {
//Computation of Access token status
if (needToken) {
//Token header and body construction
return this.http.post(token_url, token_body, token_header).map(
(res: Response) => {
//Token Success
}
)
.flatMap(
success =>
this.http.post(url, body, header) //Actual API
)
.map((res: Response) => {
//Actual API Success
}
}
else {
return this.http.post(url, body, header).map(
(res: Response) => {
//API Success
}
)
}
}
如果令牌到期时有多个API调用,则将执行Token标头和主体构造过程,甚至在Token API响应之前,其他API也会调用令牌API。
Angular prevent multiple token refresh on asynchronous requests
我尝试了上面的答案,但是由于我们的函数返回Observable,它指出Promise不能分配给Observable。
我遇到了许多排队API请求的示例,但没有一个产生期望的结果。
当令牌Token的调用尚未响应时,如何使调用API排队,然后继续使用排队API?
在这种情况下,当已经有对Access令牌API的调用并返回时,正在等待的API应该转到else部分。
请帮助我。谢谢。
答案 0 :(得分:0)
根据您的需求-这是带有令牌管理上下文的HttpInterceptor实现的摘要:请注意,为了更好地分离我使用的关注点:
一般的authService,它负责令牌管理(从服务器询问,保存在缓存中等)。
行动经理-负责做出下一步决定。
import { Injectable } from '@angular/core';
import {HttpRequest,HttpHandler,HttpEvent,HttpInterceptor , HttpResponse , HttpErrorResponse} from '@angular/common/http';
import {Observable} from "rxjs";
import {tap} from "rxjs/operators";
import {HttpHandlerService} from "../../http-handler.service";
import {ActionsService} from "../../../actions/actions.service";
import {AuthService} from "../../../../core/auth/auth.service";
@Injectable({
providedIn: 'root'
})
export class TokenInterceptorService implements HttpInterceptor{
constructor(
private _actionsManager : ActionsService,
private _authService : AuthService
) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
//Part 1 - adding headers - only for relevant apis
var accessToken = this._authService.getToken();
let authorizationHeader = accessToken ?
{'Authorization' : 'Bearer ' + accessToken , 'content-type' : 'application/json'}:
{'Authorization' : 'Basic ' + this._authService.getBasicToken() , 'content-type' : 'application/x-www-form-urlencoded'};
request = request.clone({
setHeaders: authorizationHeader
});
//Part 2 - handling request and responses
return next.handle(request).pipe(
tap(
(event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// do stuff with response if you want
}
},
(err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401 || err.status === 403) {
this._actionsManager.onEvent("unAuthorizedResponseFromServer");
}
}
}
)
);
}
}