Observable Mapping
Angular RxJS SPA Typescript Visual Studio Code

How to use the RxJS Map and Tap Operators in Angular Components

Welcome to today’s post.

In today’s post I will explain what the Map and Tap operators are in the RxJS asynchronous library, how they are used and when they can be used within an Angular application.

In previous posts I discussed other RxJS operators such as SwitchMap for controlling observable flow, Pipe for flattening structures, Subscribe for subscribing to observables, CombineLatest to synchronize dependent data, and BehaviorSubject to synchronize data loading.

The operators Map and Tap are not as challenging syntactically to apply, however they are useful in many more situations that do not require data to be synchronized.

What is the Map Operator?

When a data object is required to be mapped from one set of properties and transformed into another set of properties, we make use of the Map operator.

How do we use the Map operator?

The Map operator is used when we wish to transform an observable value to another observable value. The value can be a single value or an object with properties.

An example is the transformation of a list of objects, where the objects are of type Genre:

export class Genre
{
    public id: number;
    public genre: string;
}

After returning the list of genres from a subscription, we can transform the list into a list of strings with the following mapping:

The result is an array of strings:

[
  "Childrens", 
  "Family sage", 
  "Fantasy", 
  "Fiction", 
  "Folklore", 
  "Horror", 
  "Mystery", 
  "Non-fiction", 
  "Sci-fi"
]

The above is a basic example of how we have used the Map operator to flatten a more complex structure into a more convenient one such as a linear array. In a previous post I showed an alternative way to flatten data object structures using the Pipe and Map operators.

Another example is the transformation of a list of book objects, where the genres are in initial cap case. The following mapping transforms the array of books into an array of book objects with the values of the genre property transformed to lower case:

this.books = books.map(b => {
    if (b.genre)
        b.genre = b.genre.toLowerCase();
    return b;
});

The resulting array would contain book objects with the converted genre value as shown:

Object {
    id: 7, 
    title: "And Then There Were None", 
    author: "Agatha Christie", 
    genre: “fantasy”, 
    …
}

What is the Tap Operator?

When we require the use of data properties without mapping data from the original data object, we make use of the Tap operator. The Tap operator applies a side-effect (or function) to the source observable object without modifying it.

When do we use the Tap operator?

The Tap operator is used to apply a side-effect on an observable value without affecting the value. The most common use for the Tap operator is to log the value that is returned from an observable. This is useful for debugging values that are emitted from an executed observable, such as those from a Subscribe() operator.  

In the following observable we tap the observable output when it completes by logging the value of the observable:

this.genreList$ = this.lookupService.getGenres().pipe(
    tap(genres => {
        if (!genres)
            return;
        console.log("number of genres  = " + genres.length);        
        this.genres = genres.map(g => g.genre);
    }
));

As I mentioned, the Tap operator does not execute until the observable executes and returns a result from the subscription. An example could be waiting on multiple subscriptions:

combineLatest(
    this.booksList$.pipe(
        tap(val => { console.log("returning books: ", val); })
    ), 
    this.genreList$.pipe(
        tap(val => { console.log("returning genres: ", val); })
    )               
).subscribe(([books, genres]) => {
    if (!books)
        return;
    if (!genres)
        return;
    ….

When the above subscriptions return, the corresponding observables are logged as shown:

The Map and Tap operators are probably the two most utilised operators in the RxJS library. We have seen how to utilise the above operators in a few different scenarios within an Angular application. There are several other ways to map observables in Angular and they may be discussed in a future post.

That is all for today’s post.

I hope you found this post useful and informative.

Social media & sharing icons powered by UltimatelySocial