Practical RxJS and Angular

A practical example showing RxJS in combination with Angular

Working with RxJS is a little bit like having superpowers: your powers allow you to do extraordinary things, but they’re easy to misuse, and when that happens — it can be quite dangerous!

In this article, I want to talk about practical scenarios that I found useful while working with Angular and RxJS, going through useful patterns you may use and what to look out for.

Starting from a basic situation which only involves displaying a list, we will move on to more complex situations such as stopping ongoing requests, delaying user’s input and storing data with Subjects.

The Basics of RxJS

Getting and Displaying data with HTTP Client

In this example, we will be fetching repositories from Github’s API with Angular’s HTTP Client and we will display it as a list. This is what the component will look like:

Told ya it was simple!

Let’s assume we have a functioning Angular workspace created with the CLI, and that we created a new route called GithubRepositoriesComponent. This is what it looks like initially:

For simplicity’s sake — we will code all the logic within the component. Not something I’d recommend though!

Next, we do the following things:

we import HttpClient via Dependency Injection

we declare two methods: onTextChange, which is simply a handler for the input element, and fetchRepositories, which is responsible for performing the request to the API

we assign the observable returned by the HTTP client to searchResult$

Then, we subscribe to searchResult$ *not* in the component but in the template thanks to the async pipe. Yes — instead of subscribing within the component and assigning the resulting value to a local property, we let the async pipe subscribe to it.

But as you may have noticed, this is very basic and a pretty rusty search form. Let’s improve it a little thanks to some RxJS magic.

The templates are using some helpful Bootstrap classes for styling

Skipping requests

We want to be nice programmers, therefore we try to never consume precious resources from our services. RxJS helps us thanks to its powerful operators, but unfortunately, our initial solution has some problems:

if we enter a white-space, the request gets made again

requests run as soon as the model gets changed

if the user types something before the request has finished, the request keeps running

We can use a few new operators to avoid these issues, but we also need to refactor our code a little.

This is what we will do next:

instead of re-assigning our observable every time the model changes, we create a single stream created when the component is initiated. To do this, we introduce a Subject, that is a stream of queries

we trim and normalize our queries stream, so we can filter empty queries

empty queries we add the operator debounceTime(500) in order to debounce the queries every 500 milliseconds

the queries every 500 milliseconds we add distinctUntilChanged, which will skip requests if the query was entered consecutively

requests if the query was entered consecutively we map the queries stream to a stream of requests with switchMap

Consider the following changes to our initial solution:

Why switchMap? switchMap not only map queries to HTTP requests but will also cancel any ongoing request. See the following:

I entered a search term likely to take a lot of time, so I had enough time to re-enter a term while the search request was running.

As you can see in the network tab, the first three requests were canceled!

Yay! 🎉