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.
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.
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.
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. 🥚