catchError()
Operator
To start with, you can almost think of the catchError()
operator as similar to the built-in try...catch
operator in JavaScript.
The catchError()
Operator catches an error notification along with the original Observable that emitted the error notification, and returns a new Observable.
The catchError()
operator can be useful performing a side effect when an error notification is emitted.
You can also use the catchError()
operator for retrying the source Observable that produced the error notification, however, be warned that this can result in the creation of Observables that recursively, and endlessly, emit error notifications.
Finally, the catchError()
will catch error notifications that occur as a result of cold Observable producing an error or any operator that accepts a function from producing an error.
The catchError()
operator will not catch uncaught errors that occur during the production of values in a hot Observable, or during the subscription of a consumer to an Observable.
Example
Let's look at an example:
import { defer, Subject, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
const subject = new Subject<number>();
defer(() => {
console.log('defer');
return subject;
})
.pipe(
tap((value) => {
if (value > 1) {
throw new Error('Error emitted by throw');
}
}),
catchError((error, caught) => {
console.error('catchError', error);
return throwError(error);
})
)
.subscribe({
error: (e) => console.error('observer', e),
next: (value) => console.log('next', value),
complete: () => console.log('complete')
});
subject.next(1);
subject.next(2);
In the code example above we are using the catchError()
operator to catch the error notification produced by the tap()
operator as a result of the throw
JavaScript operator when the value is greater than 1
.
Here is the expected result of the code above:
- First, the
defer()
operator logs the message "defer" to the console upon the first subscription. - Next, the Subject, which is a hot Observable, emits a value of
1
. - The
next
function is invoked in the Observer with the value of1
that is logged to the console. So far, all is good, no errors have been emited by the source Observable. - Then, the Subject emits a value of
2
. - In this instance the
tap()
operator checks the value and uses the JavaScriptthrow
operator to throw an exception. Internally, thetap()
operator wraps the function invocation in a try...catch, and when an error occurs, returns a new Observable that immediately emits an error notification. - The
catchError
subscribes to the incoming Observable and listens for the error notification, and only the error notification. When the error notification is emitted by the source Observable, thecatchError()
operator invokes the provided selector function. The selector function receives as arguments the error notification value and the source, orcaught
, Observable that emitted the error notification. Within thecatchError()
operator we first log theerror
to the console and then return a newObservable
that is created by thethrowError()
operator, specifying theerror
value.
What do you think are the messages that we will see in the console?
There should be four messages in our console:
- defer
- next 1
- catchError Error
- observer: Error