Check out myAngular article series with live demos and Facebook group Angular - Advanced Topics

Lettable Operators in RxJs

Torgeir "Tor" Helgevold
- JavaScript Developer and Blogger
Published: Sun Oct 08 2017

In this post I will show how to use RxJs “lettable” operators in an Angular application.

In RxJs 5.5 (currently in beta) there are great improvements to how operators are imported. Instead of operator imports without exports, we will now be able to import the operator symbols directly.

What does that mean?

Basically, instead of doing:

import ‘rxjs/add/operator/switchMap’

We can do:

import {switchMap} from ‘rxjs/operators’

Not only is this a lot more in line with how most libraries handle ES6 import/export statements, its’ also much better for bundlers like Webpack and Rollup.

The old ‘rxjs/add/operator/switchMap’ syntax is really bad for tree shaking since it patches the prototype of Observable directly. Every time you import an operator, the operator is added to Observable.prototype.

Just take a look at the example from switchMap.js below:

Source: node_modules/rxjs/add/operator/switchMap.js

"use strict"; var Observable_1 = require('../../Observable'); var switchMap_1 = require('../../operator/switchMap'); Observable_1.Observable.prototype.switchMap = switchMap_1.switchMap;

Here, importing rxjs/add/operator/switchMap has the side effect of mutating the Observable.prototype directly.

Since most tree shakers are limited to “shaking” at the statement level, this addition to the prototype can’t be undone, even if you don’t use the associated operator. This is why module imports with side effects are generally discouraged.

New Way

The new operators are tree shakable since they are like regular imports, without mutating side effects.

So how does this change things when using operators in code?

The only good thing about the old approach is that it gave us a nice fluent api. Each operator returned an Observable with access to all other included operators via the prototype.

When you import each operator individually you forgo dot operator chaining. This makes sense since the operators no longer return an object with references to all other included operators.

Instead there is a new pipe function that let’s you define a comma separated sequence of operators.

Let’s show how this works by looking at some actual code:

The Angular example below uses the new operator syntax to do switchMapping and mapping of http requests.

import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Subject } from 'rxjs/Subject'; import { switchMap, map, tap } from 'rxjs/operators'; @Component({ selector: 'app-root', template: `<div> <div><button (click)="loadCountry('usa')">USA</button></div> <div><button (click)="loadCountry('denmark')">Denmark</button></div> <div><button (click)="loadCountry('germany')">Germany</button></div> <div><button (click)="loadCountry('argentina')">Argentina</button></div> Msg: {{capitol}} </div>` }) export class AppComponent { private countrySelected = new Subject<string>(); capitol: string; constructor(private http: HttpClient) {} loadCountry(key) { this.countrySelected.next(key); } ngOnInit() { this.countrySelected .pipe( switchMap(country => { return this.http.get(`/country-info/${country}.json`); }), tap(country => console.log(country)), map((country: any) => `Welcome to ${country.capitol}`) ) .subscribe((capitol: string) => { this.capitol = capitol; }); } }

Here we have defined a sequence of observables by listing the operators as arguments to the pipe function.

There is of course a slight difference from the familiar dot chaining, but everything you know about RxJs operators still applies to the new way.

Keywords

Some of the RxJs operator names collide with JavaScript keywords. This means some of them have to be renamed to stand on their own as JavaScript symbols. One such example is “do”. To get around this the do operator has been renamed to “tap”. This is unlikely to affect many of the operators, but catch is another example of this.

If you liked this article, share it with your friends on social media:

We also have a new Facebook group about advanced Angular topics.

I invite you to follow me on twitter