SHARE
Facebook X Pinterest WhatsApp

Graceful RxJS Error Handling

Jun 17, 2021

My organization’s applications make extensive use of the RxJS library to subscribe to APIs that shuttle data to and from databases and information providers. If you’ve spent any amount of time on the Internet, you are no doubt all-too aware that making calls across the wire are prone to all manner of hiccups. These can stem from network congestion, hardware failure, or application bugs. For those reasons, you need to handle your RxJS subscriptions with care. Part of this includes making sure to close active subscriptions once they are no longer required. The other way to guard against the unexpected is to employ rigorous error handling. Due to their asynchronous nature, the standard try/catch block won’t cut it. Instead, RxJS provides a few of its own mechanisms for gracefully managing the inevitable errors that come with network calls. This article will focus on two of these: Subscribe Callbacks and the catchError operator.

The Subscribe Error Callback

In addition to an Observer or Function, the subscribe() method also accepts two additional Function parameters: one for error handling and a another that executes upon successful completion. You can see them here in VS Code:

subscribe() method RxJS

 

Below is an example of an API call that fetches user settings from a data store. Should an error occur, the viewType is set to the default and the error is rethrown:

this.userService.getSettings(userid)
.subscribe(userSettings => {
this.viewType = userSettings.settings['viewType'] || this.viewSelectionValues.circle;
},
error => {
this.viewType = this.viewSelectionValues.circle;
if (error.status && error.status !== 404) {
throw error;
}
});

In this case, the error handler is actually performing double duty: besides setting the default view type, it also filters out 404 errors, which signify that there were no settings found for that user. This is not a true error because it is expected for new users.

The catchError Operator

The Subscribe Error Callback should be your first choice for RxJS subscription error handling. However, this approach has some limitations. For example, there’s no way to recover from the error or emit a fallback value that replaces the one that we were expecting from the API. For that, there’s the catchError operator. Like most RxJS operators, catchError is really a function that takes in an input Observable, and outputs an Output Observable. Should an error occur, catchError passes the error to the error handling function. That function is then expected to return an Observable which is going to be a replacement Observable for the stream that just errored out.

In this refactored version of our first example, the catchError operator is employed to intercept errors before the subscribe. In the catchError handler function, the error is discarded and a default value is provided. Thus, the error handler is never invoked:

this.userService.getSettings(userid)
.pipe(
catchError( err => of({settings: this.viewSelectionValues.circle}) )
)
.subscribe(userSettings => {
this.viewType = userSettings.settings['viewType'] || this.viewSelectionValues.circle;
},
error => console.log('HTTP Error', error));

Rethrowing the Error

Although catchError has the ability to swap out the current observable with a new one, you can still throw an error if you like. To do that, return the results of the throwError() function. You can pass in the original error, or a new, customized one:

this.userService.getSettings(userid)
.pipe(
catchError(err => {
if (error.status && error.status !== 404) {
console.log('Error encountered while fetching user settings!', err);
return throwError(err);
}
else {
return of({settings: this.viewSelectionValues.circle});
}
}
)
.subscribe(userSettings => {
this.viewType = userSettings.settings['viewType'] || this.viewSelectionValues.circle;
};

Retrying after an Error

Although we can’t recover after a stream errors out, there is nothing stopping us from re-subscribing to the stream’s source Observable (i.e. the service). The secret to retrying is the retryWhen operator. It automatically retries an observable on error:

let retryAttempts = 0;
this.userService.getSettings(this.userid)
.pipe(
retryWhen(errors =>
errors.pipe(
delayWhen(() => {
console.log(`Retry attempt #${++retryAttempts}`);
return timer(2000);
}),
take(3)
)
)
)
.subscribe(userSettings => {
this.viewType = userSettings.settings['viewType'] || this.viewSelectionValues.circle;
};

retryWhen Extras!

One important thing to keep in mind about the retryWhen Operator, is that the function that defines the Notification Observable is only called once. If you want to try a few times, you can include the take() operator. It’s even more powerful when you combine it with delayWhen(). The latter causes retryWhen to retry after the duration specified via the timer() operator.

Note that you’ll have to import RxJS Objects and operators in order to use them:

import { Observable, timer } from "https://cdn.skypack.dev/rxjs";
import { retryWhen, tap, delayWhen, take } from "https://cdn.skypack.dev/rxjs/operators";

Here’s the demo on Codepen.io. It shows how to use The Subscribe Error Callbacks as well as the retryWhen operator:

You’ll want to open the built-in console to see logging output.

Conclusion

Proper handling of errors is critical to working with asynchronous services over a network due to the sheer number of problems that can arise. Between the RxJS library’s Subscribe Callbacks and the catchError operator, you can choose to gracefully handle an error or let it flow through to alert the user.

Recommended for you...

The Revolutionary ES6 Rest and Spread Operators
Rob Gravelle
Aug 23, 2022
Ahead of Time (AOT) Compilation in Angular
Tariq Siddiqui
Aug 16, 2022
Converting a JavaScript Object to a String
Rob Gravelle
Aug 14, 2022
Understanding Primitive Type Coercion in JavaScript
Rob Gravelle
Jul 28, 2022
HTML Goodies Logo

The original home of HTML tutorials. HTMLGoodies is a website dedicated to publishing tutorials that cover every aspect of being a web developer. We cover programming and web development tutorials on languages and technologies such as HTML, JavaScript, and CSS. In addition, our articles cover web frameworks like Angular and React.JS, as well as popular Content Management Systems (CMS) that include WordPress, Drupal, and Joomla. Website development platforms like Shopify, Squarespace, and Wix are also featured. Topics related to solid web design and Internet Marketing also find a home on HTMLGoodies, as we discuss UX/UI Design, Search Engine Optimization (SEO), and web dev best practices.

Property of TechnologyAdvice. © 2025 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.