簡體   English   中英

Angular防止異步請求刷新多個令牌

[英]Angular prevent multiple token refresh on asynchronous requests

我所有的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 ...組合。

更新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() ,獲取令牌,然后調用請求,但是對於每個請求,我現在得到以下錯誤:

在此處輸入圖片說明

我注意到服務調用返回以下響應 ,這當然會導致e.json is not a function異常:

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

我認為這也是我需要投射的東西嗎?

您可以像這樣調用updateToken()來創建自己的Promise:

@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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM