Example 1: Trigger retry after specified duration
( StackBlitz | jsBin | jsFiddle )
// RxJS v6+import { timer, interval } from 'rxjs';import { map, tap, retryWhen, delayWhen } from 'rxjs/operators';//emit value every 1sconst source = interval(1000);const example = source.pipe(map(val => {if (val > 5) {//error will be picked up by retryWhenthrow val;}return val;}),retryWhen(errors =>errors.pipe(//log error messagetap(val => console.log(`Value ${val} was too high!`)),//restart in 6 secondsdelayWhen(val => timer(val * 1000)))));/*output:012345"Value 6 was too high!"--Wait 6 seconds then repeat*/const subscribe = example.subscribe(val => console.log(val));
Example 2: Customizable retry with increased duration
( StackBlitz )
import { Observable, throwError, timer } from 'rxjs';import { mergeMap, finalize } from 'rxjs/operators';export const genericRetryStrategy = ({maxRetryAttempts = 3,scalingDuration = 1000,excludedStatusCodes = []}: {maxRetryAttempts?: number,scalingDuration?: number,excludedStatusCodes?: number[]} = {}) => (attempts: Observable<any>) => {return attempts.pipe(mergeMap((error, i) => {const retryAttempt = i + 1;// if maximum number of retries have been met// or response is a status code we don't wish to retry, throw errorif (retryAttempt > maxRetryAttempts ||excludedStatusCodes.find(e => e === error.status)) {return throwError(error);}console.log(`Attempt ${retryAttempt}: retrying in ${retryAttempt *scalingDuration}ms`);// retry after 1s, 2s, etc...return timer(retryAttempt * scalingDuration);}),finalize(() => console.log('We are done!')));};
import { Component, OnInit } from '@angular/core';import { catchError, retryWhen } from 'rxjs/operators';import { of } from 'rxjs';import { genericRetryStrategy } from './rxjs-utils';import { AppService } from './app.service';@Component({selector: 'my-app',templateUrl: './app.component.html',styleUrls: [ './app.component.css' ]})export class AppComponent implements OnInit {constructor(private _appService: AppService) {}ngOnInit() {this._appService.getData(500).pipe(retryWhen(genericRetryStrategy()),catchError(error => of(error))).subscribe(console.log);// excluding status code, delay for logging claritysetTimeout(() => {this._appService.getData(500).pipe(retryWhen(genericRetryStrategy({scalingDuration: 2000,excludedStatusCodes: [500]})),catchError(error => of(error))).subscribe(e => console.log('Exluded code:', e.status));}, 8000);}}
retryWhen 📰 - Official docs
Error handling operator: retry and retryWhen
🎥 💵 - André Staltz
📁 Source Code: https://github.com/ReactiveX/rxjs/blob/master/src/internal/operators/retryWhen.ts