RxJS Pattern

Introduction

In this post we are going to cover few of RxJS pattern which we use often.

  • Declarative Data Access Pattern
  • Retrieve on Action Pattern
  • Shape on Action Pattern
  • Retrieve Related data Pattern

Declarative Data Access Pattern

To understand it better lets first see the Classic Pattern Retrieving Data.

Following is a very classic data retrieval code where we have a function inside a service which will fetch the data and then the component can subscribe to service call and can display data:

Declarative Approach

Following shows how we can transform above procedural approach with a declarative one:

Note that Its much shorter, no need of onInit, onDestory life-cycle hook and subscribe/unsubscribe because async pipe does this automatically.

So, this is Declarative Data Access Pattern.

Retrieve on Action Pattern

Think of user select a category (Action) to filter Products or a student filter notes based on subject category.

How do we deal with actions in RxJS? We use Subject or Behavior Subject.

Common Pattern: Subject or Behavior Subject

Component

HTML

UI

Now, when user click on a different category, we want to show corresponding books on the right-side (filter action) which is selectCategory method in component.

Following is one implementation which has issues

however, to unsubscribe from an inner observable and flatten the results, we can use a higher-order mapping operator.

Common Higher-order mapping operators

  • switchMap: stops current operation and start a new operation.
  • concatMap: Perform each operation one at a time, in order.
  • mergeMap: Perform each operation concurrently.

Higher-order operators

  • Auto subscribe to inner-observable
  • Also flatten result
  • Auto un-subscribe from inner-observable

For our purposes, switchMap is a good fit because if user change mind and select a different category; it will stop and cancel the first one and return the newly selected category result.

and following is the result after these changes:

So, this is a simple implementation of Retrieve on Action Pattern.

Shape on Action Pattern

Example: Show details of a Product or Book.

To start with we setup an action Stream in booksService when user select a book on user interface:

Now we have two streams

  • books$
  • bookSelectedAction$

How we’re going to work with the two of them together?

Tip: To work with multiple streams, use a Combination operator.

CombineLatest:

Nice thing there, if you’re doing a multiple retrieves, it will not continue and try to work with all that data, till it actually received all of it. So that’s great when you have to hit multiple endpoints to retrieve the data you need for an operation.

Merge:

Merge is best used when you’re merging things of like types. For typing purposes, you really don’t want to emit into same stream a customer and then an order and then odd things. You’ll use it e.g. if you get customers from one endpoint and potential customers from another endpoint and you wanna merge them into one list.

ForkJoin

It only starts its pipeline when all observables completes. So you don’t wanna ForkJoin an action Observable because they’re setup to not complete until you are leaving the page.

With forkJoin, when all the observables you’re joining complete, you emit the last value form each observable into array.

For our purposes, lets use combineLatest as follows

Following is the BookComponent code and HTML Markup

HTML

User Interface

Next, lets see an example where we fetch book data from server based on the selected book:

We’ll need this for our next example, so we’ll continue with this implementation.

We are now displaying book data on the User Interface. However, we would like to display authors information as well along with book. Lets see next Retrieve Related Data Pattern.

Retrieve Related Data Pattern

Example: We want to list book’s authors (or a product’s suppliers)

  • One Author (we can use approach similar to above when loading one detail)
  • Many Authors

Following is a simple UI where we want to show all authors for a book

Lets see how can we achieve this.

For this example, I have made few changes to endpoints which now returns a list of author ids along with a book information:

and then setup an endpoint to retrieve author information as follows

so, we’ll be calling this endpoint for each id in the author_ids array in above example. So, for similar kind of situations where you have an array of ids to retrieve data for, this approach can be checked.

First attempt (many authors) – Not best approach but easy to understand

So, we’ve our selectedBook$. We’ll pipe that one through another pipeline:

We are using switchMap as user can select a different book, so this is for that purpose.

Why mergeMap and not switchMap in below lines? because for ids e.g. [1,2,3] it will switch and we’ll only get last id data which is not what we want here.

If we use concatMap, it’ll get one data, wait, then two, wait and then three.

With mergeMap, it says, ok, I need 1,2,3 and then starts collecting them.

toArray helps us to get the set result.

Better Implementation

Now, check the following implementation which uses forkJoin:

Here, we’re gonna take each of ids using the map and issuing all those get requests and forkJoin will automatically subscribe to each one of them and wait for all of them to finish and then return the result as an array. Following is the same results on the UI.

Summary

In this post, we learned few common RxJS pattern and their usage with practical examples.

backend and frontend repos. Let me know if you have some questions and/or comments. Till next time, Happy coding.