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: 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.