Angular阻止异步请求上的多个令牌刷新

时间:2017-05-16 12:40:27

标签: javascript angular rxjs

我的所有http请求都会通过自定义 HttpService 。此服务在发送请求之前刷新令牌。

它工作正常,但如果加载的页面有多个http请求,它会多次刷新令牌。例如,如果页面通过服务有10个请求,则表示令牌刷新10次。

我试图通过示例代码来描述这个:

已加载的页面和已使用的服务

export class Page1 implements OnInit {
    constructor(
        private service1: Service1,
        private service2: Service2
    ) { }

    ngOnInit() {
        this.service1.getData...
        this.service2.getData...        
    }   
}

@Injectable()
export class Service1 {
    constructor(
        private httpService: HttpService
    ) {}

    getData(): Observable<any> {
        return this.httpService.get(.....)
            .map((response: Response) => {
                return response.json();
            });
    }
}
@Injectable()
export class Service2 {
    constructor(
        private httpService: HttpService,
        private service1: Service1
    ) {}

    getData(): Observable<any> {
        return this.httpService.get(.....)
            .map((res: Response) => res.json().response)
            .flatMap((newItem: Item) => {
                    this.service1.getData(...)
            });
    }
}

自定义http服务

@Injectable()
export class HttpService extends Http {

    constructor (backend: XHRBackend, options: RequestOptions) {
        .............
    }

    request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {

        ................

        if(tokenNotExpired('access_token')){ // if token is NOT expired

            return super.request(url, options);

        }else{  // if token is expired

            return this.updateToken()
                .flatMap((result: boolean) => {
                    return this.request(url, options);  
            });
        }
    }

    updateToken(): Observable<boolean> {

        // set the new token
        .....

    }
}

如何通过在que中设置这些请求来保留每个请求的令牌刷新,并仅在新令牌准备就绪时发送它们?

注意:我不知道是否有问题,但服务请求可以由flatMapforkJoin .... <组合/ p>

更新1

我已根据 @bviale 的答案更新了我的代码。

request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {

    ................

    if(tokenNotExpired('access_token')){ // if token is NOT expired

        return super.request(url, options);

    } else {  // if token is expired

        // There is already a call to updateToken() in progress,
        // wait for it to finish then process the request
        if (this.updateTokenPromise) {
            return Observable.fromPromise(return this.updateTokenPromise.then(() => {
                return this.request(url, options);  
            }));
        }
        // Start to call updateToken(), then resolve the promise
        else {
            this.updateTokenPromise = new Promise((resolve, reject) => {
                this.updateToken().toPromise()
                    .then((result: boolean) => {
                        resolve(result);
                    });
            });

            return Observable.fromPromise(return this.updateTokenPromise.then(() => {
                return this.request(url, options);
            }));
        }
    }
}

我更新的request()方法完全停止请求,只调用updateToken()一次,获取令牌,然后调用请求但是对于每个请求,我现在收到以下错误:

enter image description here

我注意到服务调用会返回以下响应,其中会导致e.json is not a function异常:

Object { _isScalar: false, source: Object, operator: Object }

我认为这也是我需要施展的东西吗?

1 个答案:

答案 0 :(得分:0)

当您像这样致电updateToken()时,您可以创建自己的承诺:

@Injectable()
export class HttpService extends Http {

    private updateTokenPromise: Promise<any>;

    constructor (backend: XHRBackend, options: RequestOptions) {
        .............
    }

    request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {

        ................

        if(tokenNotExpired('access_token')){ // if token is NOT expired

            return super.request(url, options);

        } else {  // if token is expired

            // There is already a call to updateToken() in progress,
            // wait for it to finish then process the request
            if (this.updateTokenPromise) {
                return this.updateTokenPromise.then(() => {
                    return this.request(url, options);  
                });
            }
            // Start to call updateToken(), then resolve the promise
            else {
                this.updateTokenPromise = new Promise((resolve, reject) => {
                    this.updateToken()
                        .then((result: boolean) => {
                            resolve(result);
                        });
                });

                return this.updateTokenPromise.then(() => {
                    return this.request(url, options);
                });
            }
        }
    }

    updateToken(): Observable<boolean> {

        // set the new token
        .....

    }
}

这样您就不会有updateToken()

的多个并行调用