LiveLoveApp logo

Error Notification

Error Notification

If an error occurs during the production of values then the Observable emits an error notification.

While there are a few ways to be notified of an error, for now we'll learn how an Observer is notified.

It is also important to understand that error notification is part of your contract with an Observable and the operators available in RxJS. If an error occurs you need an effective way to handle errors, throw errors, retry upon error, and execute code regardless of whether an error has occurred or is caught.

Finally, we should also understand that when an error occurs the Observable has ended. Therefore, Observers will receive the error notification and will not receive any further notifications, including the completion notification.

Observer's error Property

The Observer's error property enables us to be notified of an error. The Observer's error property is a function that will be invoked with the error, which may be a JavaScript Error object, but can be any error value that is emitted by the source Observable.

Let's look at an example:

import { Observable } from 'rxjs';

const observable = new Observable((subscriber) => {
  subscriber.error('Oops!');
});

observable.subscribe({
  next: (value) => console.log(value),
  error: (e) => console.error(e),
  complete: () => console.log('complete'),
});

See the example on codesandbox

In the example above:

  • First, we create a new Observable.
  • We specify the subscriber callback function that accepts the Subscriber.
  • We invoke the error() method on the subscriber.
  • Finally, we provide an Observer to the subscribe() method.
  • Note, the error property of the Observer uses the console to log out the error notification.

Let's look at another example. In this example we'll simply throw a new exception rather than using the error() method on the Subscriber.

import { Observable } from 'rxjs';

const observable = new Observable((subscriber) => {
  throw new Error('Oops');
});

observable.subscribe({
  next: (value) => console.log(value),
  error: (e) => console.error(e),
  complete: () => console.log('complete'),
});

See example on codesandbox

In the example above we did not use the error() method on the Subscriber. Rather, we relied on RxJS to catch the error for us.

If an error occurs during the production of values, we can either allow RxJS to catch the error and emit the error notification or we can explicitly catch the error.

Let's look at an example where we want to catch the error.

import { Observable } from 'rxjs';

const observable = new Observable((subscriber) => {
  try {
    throw new Error();
  } catch (error) {
    subscriber.error('An error has occurred');
  }
});

observable.subscribe({
  next: (value) => console.log(value),
  error: (e) => console.error(e),
  complete: () => console.log('complete'),
});

See example on codesandbox

We may have some code that we consider risky (here we are just throwing an exception for the sake of brevity) within the production of values in the Observable. In that case, we use the try...catch operators to catch a potential exception and manually invoke the error() method on the subscriber.

What about try...catch?

When using Observables we should not use the try...catch operators outside of the subscriber function. This is because all error cases are asynchronous. This means that try/catch will not be able to catch an error that occurs in either the production of next notification values in a cold Observable or within an operator that accepts a function.

To reiterate, part of the contract when using Observables with RxJS is that the Observable will catch runtime exceptions and emit an error notification that we can then appropriate respond to.