RxJS in Angular – Make your code more Reactive and Declarative

Introduction

In previous post, we started with the basics of RxJS and observables. We saw few examples of creating observables from existing data and various RxJS operators to transform, filter and process observables.

Today, we’ll build upon those learning and see how to work with HTTP data using RxJS. If you haven’t already you can check the previous post on this link.

Setup

I’ll be using an existing angular application and if you are following along, this is the same code base from my other angular articles.

The source code is available from this git repo.

I’ve added one component to encapsulate demos for this post.

Angular Http Client

The Http Client in @angular/common/http offers a simplified client HTTP API for Angular applications that rests on the XMLHttpRequest interface exposed by browsers. Some additional benefits of HttpClient include testability features, typed request and response objects, request and response interception, Observable APIs, and streamlined error handling. We are using HttpClient to fetch data from the server to our application.

Following code shows the UsersService which uses HttpClient

Procedural Data Retrieval

Following is how UsersComponent currently uses the UsersService to get the data and store it to local users array in component.

The template then displays the data as shown below

and following is the output

As you can see that this is a very typical pattern of retrieving data in Angular. This is a procedural approach which works ok for simpler cases, however, it can be limiting for larger and more complex applications.

Let’s see how to make this code more reactive starting with async pipe.

async Pipe

We access an observable directly in template using the async pipe. It automatically subscribes to observable when the component is initialized.

Let’s see next, how to change our code to use async pipe.

The use of async pipe doesn’t require change to our service code, only our component and template.

Let’s start with component

Instead of a simple array, we defined users$ as an observable property ($ symbol is a convention indicating that it is an observable). Also in ngOnInit() method, we no longer are subscribing. The code already started looking cleaner.

We also need to change template to use the async pipe which will automatically subscribe to the observable users$ property on the component and automatically handles unsubscribing. Following is the changed template part:

with these changes in-place, run the application again and we see the same results as before.

Benefits of async pipe

  • No need to subscribe (it is automatically done)
  • No need to unsubscribe.
  • Improved change detection.

Comparison

Following is the comparison

as you can see that code is much simpler and shorter.

Error Handling

So, how do we handle errors with this new style? Following code shows the use of pipe and catchError operator to achieve this:

catchError: catches any error that occurs on observable.

(you can simulate an error, by changing the backend URL in UsersService to some invalid address)

EMPTY: is an observable that emits no items. It immediately emits a complete notification.

Improved Change Detection

Angular uses change detection to track changes to application data so that it knows when to update UI.

There are two basic change detection strategies:

  • Default
    • Uses the default CheckAlways strategy
    • Every component is checked when any change is detected.
  • OnPush
    • Improves performance by minimizing change detection cycles.
    • Component is only checked when:
      • @Input properties change.
      • any event emits.
      • a bound observable emits (e.g. async pipe) – which is our case here

As we are now using observable, we can set changeDetection strategy to OnPush on component meta-data and minimize Change Detection cycles. This can improve display performance.

(Notice, if we change it to OnPush; errorMessage property won’t automatically update the UI, we’ll discuss later, how to handle it).

Using the async pipe, our code is more reactive. But, can we do better?

Declarative Pattern – Service

The data retrieval pattern, we are currently using is still procedural.

Here, we have a procedural call from our component to the the service, for data retrieval. Lets make this code more declarative.

In service, lets declare an observable property users$ and assign it directly to the result of http GET request:

and in component, we assign the local property to the observable property from the service:

This image has an empty alt attribute; its file name is image-94.png

So, this results in “no more getUsers() method call, no more ngOnInit() method. Its more cleaner and declarative compare to procedural approach.

Following is the comparison before and after the changes

Reacting to Errors

We discussed earlier that OnPush change detection only detects changes made to input properties, events from child components and observables bound in the template using async pipe.

Bound values set in local properties will not trigger change detection, so it will not update the UI. That’s why updating errorMessage property in our component won’t trigger change detection and error message won’t appear to the user. Lets fix this issue.

We’ve not talked about Subject yet, but for now, this is how we will convert a simple string property to an observable and then we can call .next() method to push new data to the observable.

In the template, we can now bound to this property using async pipe as follows:

With these changes, now the UI will show the error to the user when it happens.

We’ll cover subject and its variants in upcoming posts along with more RxJS examples.

Summary

In this post, we covered the basics of RxJS with procedural and declarative data retrieval patterns and saw how we can make our code more reactive and declarative with simple changes.

We saw the usage of async pipe in template and we also looked at angular change detection strategies and modified our code to utilize the OnPush strategy. We’ll cover more examples in upcoming posts.

You can check the source code available form this git repo.

The deployed sample application is available on this URL.

Let me know if you have some comments or questions. Till next time, Happy coding.

1 thought on “RxJS in Angular – Make your code more Reactive and Declarative”

Comments are closed.