A little late to the party but, I recently implemented a similar behaviour. Here is my solution:
post<T>(serviceUrl: string, data: any): Observable<T> {
return Observable.defer(() => {
return super.post<T>(serviceUrl, data);
}).retryWhen((error) => {
return this.refresh(error);
});
}
And the refresh function:
refresh(obs: Observable<any>): Observable<any> {
return obs
.switchMap((x: any) => {
if (x.status === 401) {
return Observable.of(x);
}
return Observable.throw(x);
})
.scan((acc, value) => {
return acc + 1;
}, 0)
.takeWhile(acc => acc < 3)
.flatMap(() => {
console.log('Token refresh retry');
return this.tokenRefreshService.refreshToken();
});
}
The use case is that whenever I make an HTTP request and get a 401 response, I want to do a token refresh and then retry the initial request with the new token. When a 401 occurs I use switchMap to return a new Observable, otherwise, I return an Observable.throw(x) that stops the retry logic from being executed.
And the calling code looks like this (where error is called whenever you return an Observable.throw(x)):
this.http.post(x).subscribe(response => {
...
}
}, error => {
...
}
});
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…