2017-05-16 9 views
0

すべてのhttpリクエストはカスタムHttpServiceを経由します。このサービスは、要求を送信する前にトークンが期限切れになったときにそのトークンをリフレッシュします。Angularは非同期リクエストで複数のトークンリフレッシュを防止します

正常に動作しますが、ロードされたページに複数の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で設定してリクエストごとにトークンをリフレッシュし、新しいトークンは準備ができていますか?

注:それは問題だ場合、私は知らないが、サービス要求がflatMapまたはforkJoinで組み合わせることができます....

アップデート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()を呼び出すときには、独自の約束を作成することができます。この方法では、あなたがそれをタイプ「約束 `としてエラーが発生しましたupdateToken()

+0

初めての複数の並列呼び出しを持っていません

@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 ..... } } 

'はタイプ' Observable 'に割り当てられません。 Observableの戻り値の型を 'request()'と 'updateToken()'から取り除いた後、 'resolve(result);'のために 'then'のためにコンパイルしませんでした。私もそれを削除しましたが、それ以降は、 'this.httpService.get(...)というエラーで失敗しました。トークンが期限切れになったとき、mapはupdateToken()の関数ではありません。私は 'Promise'がうまく合わないと思う:( –

+0

' Promise'と 'Observable'の間の適切なキャスティングによってこれらのエラーを取り除くことができたが、今度は別のエラーが出る。 –

関連する問題