<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1063935717132479&amp;ev=PageView&amp;noscript=1 https://www.facebook.com/tr?id=1063935717132479&amp;ev=PageView&amp;noscript=1 "> Bitovi Blog - UX and UI design, JavaScript and Frontend development
Loading

Angular |

How to Use RxJS catchError Without Unsubscribing from New Events

Learn how to effectively handle errors using RxJS catchError operator, with code examples on catching errors without unsubscribing or missing new events.

Igor Ciric

Igor Ciric

Twitter Reddit

Did you know you can use the catchError RxJS operator to catch errors without unsubscribing? It’s true! It all depends on where you plan to use the operator.

Now you can use the catchError RxJS operator in two ways:

  • Catch the error without unsubscribing; continue getting new events
  • Catch the error and unsubscribe; stop getting new events

In this post, learn how to tailor your use of catchError to fit the needs of your project!

How to Catch Errors Without Unsubscribing

In the example below, you can use the catchError operator and keep getting events from the other Observables once the error happens.

catcherror1

Here you have two observables; the first will throw an error on the third event. After the error is emitted, you will emit the value of -1 and continue getting new values from the second Observable. To achieve this, you need to apply the catchError operator specifically to that Observable.

import { interval, of, map, catchError, combineLatest, take } from 'rxjs';

const observable1 = interval(100).pipe(
  map((n) => {
    if (n === 3) {
      throw 'Some error happened';
    }
    return n;
  })
);

const observable2 = interval(100).pipe(take(5));

combineLatest([
  observable1.pipe(
    catchError((err) => { // 🟡 We used catchError specifically for this observable
      console.log('Error:', err);
      return of(-1);
    })
  ),
  observable2,
]).subscribe((result) => {
  console.log(result);
});

The output results will be:

[0,0]
[1,0]
[1,1]
[2,1]
[2,2]
🔴 Error: Some error happened
[-1,2]
[-1,3]
[-1,4]

After error happened, the value of the first Observable will be -1, and the second will be the current value that was emitted.

Check out this interactive example to get a better idea of how it works.

Catch the Error and Unsubscribe

In the typical use of catchError, you will catch the error and unsubscribe after any of the Observables emits an error. To achieve this, apply the catchError operator inside the pipe before the subscribe callback.

catcherror2

 

After the first Observable throws an error, you will catch the error and unsubscribe. The last value that will be emitted will come from catchError. In this case, it will be null.

import { interval, of, map, catchError, combineLatest, take } from 'rxjs';

const observable1 = interval(100).pipe(
  map((n) => {
    if (n === 3) {
      throw 'Some error happened';
    }
    return n;
  })
);

const observable2 = interval(100).pipe(take(5));

combineLatest([observable1, observable2])
  .pipe(
    catchError((err) => {
      // 🟡 We used catchError inside the pipe before callback
      console.log('Error:', err);
      return of(null);
    })
  )
  .subscribe((result) => {
    console.log(result);
  });

The output results will be:

[0,0]
[1,0]
[1,1]
[2,1]
[2,2]
🔴 Error: Some error happened
null

After the Observable throw error, the last emitted value will be null. Try it yourself with this interactive example.

Without catchError Operator

If you don't use the catchError operator, the error will throw inside of subscribe callback, and you will be unsubscribed. It works similarly to using the catchError operator before subscribing callback, like in the second example.

Approaches without catchError operator can work fine if you don't want to use Observable in the template, otherwise the application will throw the error and break for, e.g. in the Angular component template using Observable via async pipe.

catcherror3
import { interval, of, map, catchError, combineLatest, take } from 'rxjs';

const observable1 = interval(100).pipe(
  map((n) => {
    if (n === 3) {
      throw 'Some error happened';
    }
    return n;
  })
);

const observable2 = interval(100).pipe(take(5));

combineLatest([observable1, observable2]).subscribe({
  next: (result) => {
    console.log(result);
  },
  error: (err) => {
    // 🟡 We are catching error inside subscribe callback
    console.log(err);
  },
});

The output results will be:

[0,0]
[1,0]
[1,1]
[2,1]
[2,2]
🔴 Error: Some error happened

Try it yourself with another interactive example.

Conclusion

Understanding how to use the catchError operator in RxJS is essential for handling errors in your project. Whether you want to catch errors without unsubscribing or stop getting new events, knowing how to tailor its use is vital. By following the examples in this post and experimenting with the interactive examples, you can become proficient in using catchError and ensure your project runs smoothly.

Do you have thoughts about catchError?

We’d love to hear them! Join the Bitovi Community Discord to chat about Angular, RxJS, or anything you’re working on. 🥚