2017-05-16 96 views
0

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

    } 
} 

我怎樣才能perevent的通過在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()只有一次,獲得令牌,然後調用請求,但對於每一個請求,我得到現在出現以下錯誤:

enter image description here

我注意到服務電話返回以下響應哪一個會導致e.json is not a function例外:

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

我認爲這也是我需要投的東西?

回答

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

+0

第一次給了錯誤爲'類型「無極多個並行調用'不可分配鍵入'Observable ''。從'request()'和'updateToken()'中移除'Observable'返回類型後,由於'then'用於'resolve(result);',所以它沒有被編譯。我也刪除了它,但之後失敗,出現錯誤'this.httpService.get(...)。當token過期時,map不是updateToken()中的函數。我猜'Promise'並不適合:( –

+0

)我可以通過'Promise'和'Observable'之間的正確鑄造來擺脫這些錯誤,但現在它又出現了另一個錯誤。請檢查我更新的問題。 –