How to use Async pipe in Angular
Posted By : Damini Sharma | 24-Aug-2019
What is the angular async pipe?
The angular async pipe permits the subscription to observables within the angular template syntax. It also takes care of unsubscribing from observables automatically.
Let's take a look at a count incrementing component's example:
import { Component } from '@angular/core' import { Observable } from 'rxjs' @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { observable: Observable<number> ngOnInit() { this.observable = Observable.create(observer => { let value = 0 const interval = setInterval(() => { observer.next(value) value++ }, 1000) return () => clearInterval(interval) }) } }
To display that value we can reference the observable property and use the async pipe to resolve the observable to the current value:
<p>{{ observable | async }}</p>
A common use case is displaying values received from a REST-Endpoint, as the angular HttpClient returns an observable.
Why should you use the async pipe?
There are many ways to subscribe to observables. The default way, certainly without angular, is to subscribe to the observable manually and update a separate property with the value:
import { Component } from '@angular/core' import { Observable } from 'rxjs' @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { observable: Observable<number> latestValue: number; ngOnInit() { this.observable = Observable.create(observer => { ... }); this.observable.subscribe(value => this.latestValue = value); } }
we can then bind to that property without using the async pipe at all:
<p>{{ latestValue }}</p>
So why to use the async pipe then?
It turns out the code above is not all we need to do!
Because we subscribed to the observable manually, we also need to manually unsubscribe. Otherwise, we risk a memory leak when the component is destroyed.
To fix this, we need to unsubscribe when the component is destroyed. The best place to do that is the ngOnDestroy lifecycle hook:
import { Component } from '@angular/core' import { Observable, Subscription } from 'rxjs' @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { observable: Observable<number> latestValue: number subscription: Subscription ngOnInit() { this.observable = Observable.create(observer => { ... }) // To be able to unsubscribe later make sure to save a reference to subscription this.subscription = this.observable.subscribe( value => (this.latestValue = value) ) } ngOnDestroy() { // Unsubscribe when the component is destroyed this.subscription.unsubscribe() } }
A cleaner and more reactive way of doing the same thing is to use the rxjs takeUntil operator with another observable/subject that we complete when the component is destroyed. In this case, the takeUntil operator is taking care of unsubscribing.
import { Component } from '@angular/core'; import {Observable,Subject, Subscription} from 'rxjs'; import {takeUntil} from 'rxjs/operators'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: [ './app.component.css' ] }) export class AppComponent { observable$: Observable<number>; unsubscribe$: Subject<void> = new Subject<void>(); latestValue: number; ngOnInit(){ this.observable$ = Observable.create((observer) => { ... }) this.observable$ .pipe(takeUntil(this.unsubscribe$)) .subscribe(value => this.latestValue = value); } ngOnDestroy(){ this.unsubscribe$.next(); this.unsubscribe$.complete(); } }
when using the angular async pipe, all this additional syntax is not necessary, as the pipe itself takes care of unsubscribing from the observable once the component is destroyed. So, the async pipe makes our code cleaner.
Also, the methods showed above do not work with the onPush change detection strategy, which is used to do performance optimizations of components. Async pipe, works just fine with that.
That is why we should definitely use the async pipe whenever possible.
How to use the async pipe with *ngIf
The Interpolation is not the only data binding the async pipe can be used with.
You can also use it with the *ngIf directive:
<p *ngIf="(observable$ | async) > 5">{{ observable$ | async }}</p>
Note, that the braces are absolutely necessary in this case.
How to use the async pipe with *ngFor
In the same way we can use the async pipe with the ngIf directive, we can use it with the ngFor directive.
To do that, the observable has to resolve to an array type, not just a single value.
items$: Observable<number[]>;
We then use it in combination with the *ngFor directive like so:
<p *ngFor="let item of items | async">{{ item }}</p>
Conclusion
In this tutorial, we learned how we can use the angular async pipe to prevent memory leaks.
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Damini Sharma
Damini is a young enthusiastic web designer who loves to explore latest, cutting edge tools and technologies in web development.