2017-01-16 31 views
4

我正試圖在我的Angular2應用程序上實現刷新標記。 我正在採取一種樂觀的態度,而不是在提出請求之前檢查訪問令牌是否過期,我正在提出請求,如果它返回了401代碼,我將刷新訪問令牌,請求新令牌並將其保存到本地存儲。在重試Observable時在HT​​TP上更改標題

這裏是我的代碼片段:

getWithParams<T>(serviceUrl: string, params: URLSearchParams): Observable<T> { 
    return super.getWithParams<T>(serviceUrl, params) 
     .retryWhen((error) => { 
      return error 
       .filter((e) => e.status === 401) 
       .scan((acc, value) => { 
        return acc + 1; 
       }, 0) 
       .takeWhile(acc => acc < 3) 
       .flatMap(() => this.tokenRefreshService.refreshToken()) 
       .delay(1000); 
     }); 
} 

它通過從本地存儲檢索它提上請求頭那super.getWithParams setsthe訪問令牌是非常重要的。

方法調用tokenRefreshService.refreshToken()獲取一個新的訪問令牌並將其保存到本地存儲。

我面臨的問題是,當請求重試時,它使用的是舊訪問令牌,也就是說,它沒有調用super.getWithParams來重新生成請求。它只是重試現有的可觀察項。

有沒有辦法再次構建請求?或查詢失敗的observable的請求標頭?

+0

這似乎是一個非常相似,你需要什麼http://stackoverflow.com/questions/39953419/get-new-ticket-then-retry-first-請求/ 39955002#39955002,http://stackoverflow.com/questions/39797698/observable-continue-calling-api-and-changing-parameters-based-on-condition。也許這也是這個http://stackoverflow.com/questions/41005674/angular-2-http-retrywhen/41014380#41014380 – martin

回答

3

其實retryWhen()重新訂閱它的來源,所以你可以使用它來你的優勢。這個例子應該模擬您的情況:

let token = 'token'; 
let counter = 0; 

const source$ = Rx.Observable.defer(() => { 
    console.log('Observable.defer(), token: ' + token); 
    return Rx.Observable.of(token); 
    }) 
    .map(token => { 
    if (counter++ < 3) { 
     throw new Error('invalid token'); 
    } 
    return token; 
    }) 
    .retryWhen((error) => { 
    return error 
     .filter(() => true) // or whatever... 
     .do(() => token = token + 'bla'); // update the token 
    }) 
    .map(token => { // create the request 
    return "I'm a request with token: " + token; 
    }); 


source$.subscribe(
    res => console.log(res), 
    err => console.log('error: ' + err), 
() => console.log('complete') 
); 

見現場演示:https://jsbin.com/roduqi/5/edit?js,console

這三次罰球無效令牌每一次更新,它是一個錯誤。

請注意,對於每一個錯誤,我都會使用Observable.defer創建一個新的源Observable。

這個例子打印到控制檯:

Observable.defer(), token: token 
Observable.defer(), token: tokenbla 
Observable.defer(), token: tokenblabla 
Observable.defer(), token: tokenblablabla 
I'm a request with token: tokenblablabla 
complete 
+0

在一個observable中包裝super.getWithParam方法調用的伎倆。輝煌! –