#rxjs #tutorial #advanced

Day 9: Error Handling & Retry Strategies

Day 9: Error Handling

In a stream, an error usually kills the subscription. We need strategies to handle this gracefully.

1. catchError

Catches an error and returns a new Observable to replace the broken one. This keeps the stream alive (or gracefully closes it).

import { of, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

const apiCall$ = throwError(() => new Error('Server limit exceeded'));

apiCall$.pipe(
  catchError(err => {
    console.error('Handled:', err.message);
    // Return fallback value
    return of('Cached Data');
  })
).subscribe(val => console.log(val));
// Output: Handled: Server limit exceeded
// Output: Cached Data

2. retry

Simply resubscribes to the source observable n times if it fails.

import { interval } from 'rxjs';
import { map, retry } from 'rxjs/operators';

interval(1000).pipe(
  map(val => {
    if (val > 1) throw 'Boom!';
    return val;
  }),
  retry(2) // Try 2 more times before giving up
).subscribe({
  next: console.log,
  error: console.error
});

3. retryWhen (Advanced)

Allows you to delay the retry. “If it fails, wait 2 seconds, then try again.” Note: In newer RxJS, use retry({ delay: ... }).

import { timer } from 'rxjs';
import { retry } from 'rxjs/operators';

source$.pipe(
  retry({
    count: 3,
    delay: (error, retryCount) => timer(retryCount * 1000) // Exponential backoff: 1s, 2s, 3s
  })
);

4. finalize

Runs logic when the observable finishes (either complete OR error). Good for turning off loading spinners.

import { finalize } from 'rxjs/operators';

this.showSpinner = true;

data$.pipe(
  finalize(() => this.showSpinner = false)
).subscribe();

Homework for Day 9:

  1. Create an observable that throws an error randomly (50% chance).
  2. Use retry(3) to make it robust.
  3. Use catchError to return “Fallback” if it still fails after 3 tries.

Tomorrow is the Grand Finale: Building a Real-World Application!