Angular - Using Single Subscription for Multiple Async Pipes

December 29, 2017 2 min read Angular

Learn how to subscribe for an observable once with multiple async pipes using 'as' keyword and local template variable.

The Issue

Let’s imagine we’ve an observable which fetches a list of users:

All right. Suppose we got a mission to display each user field by a separated list. But there is a constraint, each list will be displayed differently. Thus, the appropriate template could be:

Let’s check how many subscriptions would be created in that way by adding a log when a subscription is created:

Here are the results of the Console:

Refreshing the application and noticing that three different subscriptions were created

Three different subscriptions were created

Well, we notice that each usage of async pipe creates another subscription. Although these are three different *ngFor, we’re talking about the same observable - so we’d expect that async pipe would use a single instance of a shared subscription.

In case there is an operator on the observable, for example, a map operator which does a heavy business logic like calculating - that operator will be executed for each subscription individually.

Let’s see how to create a single subscription for users$ but still be able to use its result for each list.

The Solution

As part of Angular 4.0.0 - we introduced with the as keyword. That keyword enables assigning a local variable in the component’s template. In other words, it means we’re able to use a variable (as much as we want) which points to the evaluated result of the async pipe.

Note: In general, assigning the result using the as keyword isn’t necessarily for the async pipe but for all pipes.

To bind a local variable with the template, we need to wrap the template with the ng-container directive.

In case that you’re not familiar with the ng-container - it’s just a wrapper that enables to group multiple DOM elements (without adding an additional element to the DOM) and apply a structural directive on these elements (such as *ngFor and *ngIf).

It’s time to use the as keyword:

Basically, what we do is to assign the result from the subscription as a local variable which is named users. Notice we need a structural directive in order to interpret the as keyword and for binding the users variable with the result from the async pipe. That’s the reason we use *ngIf.

If we’d like to use the users array for other purposes (for instance, printing its length) we could use the users variable as well - as long as it’s evaluated inside that ng-container scope.

Here’s attached the final result:

Indeed, we’re done.