Learn RxJS
Search…
retryWhen

signature: retryWhen(receives: (errors: Observable) => Observable, the: scheduler): Observable

Retry an observable sequence on error based on custom criteria.

Examples

Example 1: Trigger retry after specified duration
1
// RxJS v6+
2
import { timer, interval } from 'rxjs';
3
import { map, tap, retryWhen, delayWhen } from 'rxjs/operators';
4
5
//emit value every 1s
6
const source = interval(1000);
7
const example = source.pipe(
8
map(val => {
9
if (val > 5) {
10
//error will be picked up by retryWhen
11
throw val;
12
}
13
return val;
14
}),
15
retryWhen(errors =>
16
errors.pipe(
17
//log error message
18
tap(val => console.log(`Value ${val} was too high!`)),
19
//restart in 6 seconds
20
delayWhen(val => timer(val * 1000))
21
)
22
)
23
);
24
/*
25
output:
26
0
27
1
28
2
29
3
30
4
31
5
32
"Value 6 was too high!"
33
--Wait 6 seconds then repeat
34
*/
35
const subscribe = example.subscribe(val => console.log(val));
Copied!
Example 2: Customizable retry with increased duration
1
import { Observable, throwError, timer } from 'rxjs';
2
import { mergeMap, finalize } from 'rxjs/operators';
3
4
export const genericRetryStrategy = ({
5
maxRetryAttempts = 3,
6
scalingDuration = 1000,
7
excludedStatusCodes = []
8
}: {
9
maxRetryAttempts?: number,
10
scalingDuration?: number,
11
excludedStatusCodes?: number[]
12
} = {}) => (attempts: Observable<any>) => {
13
return attempts.pipe(
14
mergeMap((error, i) => {
15
const retryAttempt = i + 1;
16
// if maximum number of retries have been met
17
// or response is a status code we don't wish to retry, throw error
18
if (
19
retryAttempt > maxRetryAttempts ||
20
excludedStatusCodes.find(e => e === error.status)
21
) {
22
return throwError(error);
23
}
24
console.log(
25
`Attempt ${retryAttempt}: retrying in ${retryAttempt *
26
scalingDuration}ms`
27
);
28
// retry after 1s, 2s, etc...
29
return timer(retryAttempt * scalingDuration);
30
}),
31
finalize(() => console.log('We are done!'))
32
);
33
};
Copied!
1
import { Component, OnInit } from '@angular/core';
2
import { catchError, retryWhen } from 'rxjs/operators';
3
import { of } from 'rxjs';
4
import { genericRetryStrategy } from './rxjs-utils';
5
import { AppService } from './app.service';
6
7
@Component({
8
selector: 'my-app',
9
templateUrl: './app.component.html',
10
styleUrls: [ './app.component.css' ]
11
})
12
export class AppComponent implements OnInit {
13
constructor(private _appService: AppService) {}
14
15
ngOnInit() {
16
this._appService
17
.getData(500)
18
.pipe(
19
retryWhen(genericRetryStrategy()),
20
catchError(error => of(error))
21
)
22
.subscribe(console.log);
23
24
// excluding status code, delay for logging clarity
25
setTimeout(() => {
26
this._appService
27
.getData(500)
28
.pipe(
29
retryWhen(genericRetryStrategy({
30
scalingDuration: 2000,
31
excludedStatusCodes: [500]
32
})),
33
catchError(error => of(error))
34
)
35
.subscribe(e => console.log('Exluded code:', e.status));
36
37
}, 8000);
38
}
39
}
Copied!

Additional Resources

Last modified 1yr ago