Hot and cold RxJs Observables

You’ve probably heard about cold and hot observables in RxJs. What does that mean, and what’s the difference?

It’s pretty straightforward:

  • A cold observable creates a new “task” for each subscriber. For instance, observables returned by the Angular HttpClient are cold. If we subscribe to the same
    observable three times, we’re firing three different HTTP requests. Another consequence is that cold observables don’t do anything unless they get subscribed to.
  • A hot observable, as you might have guessed, is the opposite. Hot observables share their data with all subscribers. They are multicast. They don’t need to be subscribed to get started. Subjects are examples of hot observables. The observables we get from Angular FormControl are hot observables, too.

I’ll share more tips on RxJs hot and cold observables in the coming weeks.

How to decide which RxJs operator to use?

There are more than 120 operators in RxJs, and with so many options, it can be challenging to decide which one we should use. We covered a few of them in this newsletter so far and mentioned websites such as Rxmarbles to learn more about these operators.

Luckily, Rxjs.dev has an interesting feature called the operator decision tree. This tool asks a few questions about what we’re trying to do and ends up suggesting one operator that answers that need.

It uses a wizard-style approach:

The tool is excellent and does save a lot of time researching operators in the documentation. I found some scenarios where it suggests deprecated options. Still, each deprecated feature has a link to its replacement, so it’s easy to find the actual operator to use from there.

RxJs Subjects: When and why?

Our RxJs topic for this week is going to be Subjects. Angular has multiple services and classes (such as FormControl) that give us access to Observables that we can subscribe to. But what if we want to create our own Observable to emit data?

While there is an Observable constructor and Observable creation functions such as of and from, none of these solutions are as powerful and feature-complete as using a Subject.

Why is that? Because Subjects check a lot of boxes for us:

  • They are multicast, which means they support multiple subscribers out of the box (an Observable does not by default)
  • They can replay values to new subscribers (BehaviorSubject and ReplaySubject do that)

Those two features are critical when building Angular apps because our data is usually handled by services, then consumed by components. For example, suppose a service fetches some data (say, the user session info upon login). In that case, it is essential for components that will be displayed later on the screen to subscribe to that information and get the current session info right away (that’s why replayability/caching the latest value is critical).

As a plus, the Subject API is incredibly straightforward:

So we have complete control over what we emit, when, and how. All with a single method: .next()

And since a Subject is a specific type of Observable, you can subscribe to it the same way: subject.subscribe(). That said, it is a best practice to expose the subject as an Observable by using the asObservable() method as illustrated here:

For more details on how to use Subjects and what are the different types of Subjects, feel free to head to my RxJs subjects tutorial.

RxJs debounceTime operator

This week’s RxJs operator is very commonly used for form validation: debounceTime.

debounceTime is going to delay emitted values for a given amount of time (in milliseconds) and emit the latest value after that period has passed without another source emission. I know it’s not super easy to describe with words.

A marble diagram for debounceTime looks like this:

In the above example, the values 2 – 3 – 4 – 5 are emitted less than ten milliseconds from one another, so they get dropped. Only five gets emitted 10 ms later.

Why is that useful for form validation? Because we usually want to wait for the user to finish typing something before triggering some asynchronous validation. For instance, if we validate a street name, it makes sense to wait for the user to stop typing for a while instead of sending HTTP requests to an API every time a new keystroke happens, which would flood the server with useless validation requests.

Using our credit card demo from yesterday, here is a different Stackblitz example where I debounce the output for 400 ms. This is the result:

You can see that the debounced value gets displayed once I stop typing for 400 ms. So that’s how I used that operator:

And then display the results side by side in my HTML template as follows:

Usually, 300 to 400 ms is an excellent spot to debounce user input, but you can try different values and see what works best.

If you want to dive deeper into asynchronous form validation, this tutorial should help: How to write async form validators with Angular?

RxJs distinctUntilChanged operator

This week, our RxJs operator of choice is distinctUntilChanged, another of these few operators with a name that is explicit enough.

distinctUntilChanged ignores unchanged values that get emitted several times:

This operator is beneficial when using RxJs to filter out data based on filters selected by the end user in the UI. For instance, it’s a way to ensure that we only trigger a data update (such as an HTTP request) when the filters have changed.

A notable feature is that you can pass a custom comparison function as a parameter to determine how to compare those values. Otherwise, the operator uses === as a default comparison, which is acceptable for basic types but not for comparing objects unless you want to compare references.

RxJs forkJoin operator

Our weekly RxJs operator is forkJoin. This operator can be applied to any number of Observables. When all these Observables complete, forkJoin emits the last value from each one of them.

A common use case for forkJoin is when we need to trigger several HTTP requests in parallel with the HttpClient then receive all of the responses at once in an array of responses:

The critical feature here is that those requests happen simultaneously, not one after the other (better performance), yet we receive the data when both have completed, which is convenient.

Another interesting syntax for forkJoin is to pass an object instead of an array as follows:

Here is a complete example of forkJoin in action.

As a reminder, my 2-hour RxJS workshop from ng-conf 2022 is also available on Youtube for free!

RxJs withLatestFrom operator

Our weekly RxJs operator is withLatestFrom, a rare example of an operator with a name that says it all.

Here’s the marble diagram for withLatestFrom:

This operator takes two or more Observables and turns them into one single Observable that emits a new value whenever the source Observable emits something new.

The important thing to note here is that only one Observable triggers updates in the output Observable. As a result, withLatestFrom is a great option when you want a user action to trigger an update in the user interface (think about data table filters, inter-connected dropdowns, etc.)

You can see a live code example here (including comments that explain the thought process) with two dropdowns that depend on one another. A selection in the first dropdown impacts the values displayed in the second one (selecting a continent filters out the countries shown in the second dropdown:

If you want a deeper dive, I have this complete tutorial on using withLatestFrom alongside other operators to implement dynamic filtering in a component.

And for even more RxJs content, my 2-hour RxJS workshop from ng-conf 2022 is now available on Youtube for free!

How to learn more about RxJs operators?

In the past weeks, we covered a few different RxJs operators in this newsletter. RxJs is the most difficult thing to learn about Angular, and that’s because the technology is a mix of concepts that are not always obvious on their own: asynchronous data and callbacks, functional programming, streams, etc.

My favorite resource to learn more about RxJs is to use a website called rxmarbles.com. Why? Because that website features interactive diagrams of RxJs operators.

Let’s take an example with mergeMap. Here’s the official definition of mergeMap:

Projects each source value to an Observable which is merged in the output Observable.

Rxjs.dev documentation

And here’s an interactive diagram from RxJs marbles for mergeMap – I just recorded my screen while interacting with the diagram by dragging data around:

They say a picture is worth a thousand words. An interactive picture is even better, and that’s exactly what rxmarbles.com is. No text, just interactive diagrams.

Note: Not all operators are documented on that website, just some of the most useful ones. At times, the operator’s signature or name is slightly different depending on the version of RxJs you’re using. Still, overall, RxJS Marbles remains one of the very best tools for understanding operators.

RxJs tap operator

The tap operator is one of the simplest RxJs operators because it doesn’t change anything to the data coming into your observable:

Why would we need a function that doesn’t do anything? We saw a first very important example that enabled us to use the async pipe earlier.

At least three important use cases are:

  • Debugging complex RxJs scenarios using console.log (as illustrated in the above marble diagram)
  • Registering side effects as the data changes (that’s what we did in our async pipe scenario)
  • Watching for completion of inner observables (when you’re combining several observables into one subscription)

In short, tap is a way to spy on what is happening inside an observable stream. Any time you want to extract some data/debug/take a look at what’s going through an Observable, tap is the easiest answer.

You can find examples for these three scenarios in my tutorial: 3 reasons to use the tap operator.

ngrxLet: A better version of the async pipe

Yesterday, we mentioned how the async pipe can be used with *ngIf or *ngFor in our templates to declare a local variable that allows us to have multiple expressions using the same data:

<div *ngIf="user$ | async as user">
   <p>First name: {{ user.firstName }}</p>
   <p>Last name: {{ user.lastName }}</p>
</div>Code language: HTML, XML (xml)

While the above code works perfectly well, it’s not always convenient to add an additional *ngIf or *ngFor in our templates. Another shortcoming of the async pipe is that it doesn’t let us know if the observable has an error or completes successfully.

This is where the ngrxLet directive can save the day, as it solves all of the above shortcomings with a straightforward syntax. Our previous example becomes:

<div *ngrxLet="user$ as user">
   <p>First name: {{ user.firstName }}</p>
   <p>Last name: {{ user.lastName }}</p>
</div>Code language: HTML, XML (xml)

And if we want to get any errors or the completion status of the observable, we can do so with more local variables exposed by ngrxLet:

<div *ngrxLet="user$ as user; error as e; complete as c">Code language: HTML, XML (xml)

You can find a complete working example here. ngrxLet can be installed as a dependency using npm (npm install @ngrx/component), and it’s important to note that it is not the entire ngrx state management library, just a tiny subset of it, so using that directive does not require using anything else from ngrx.

Here is a link to a slightly expanded version of that tutorial with more information if you want to dig deeper into it: ngrxLet – A better version of the async pipe.