Skip to content
View lessons Login
3d cartoon hands holding a phone

Unlock full course by purchasing a membership

The Importance of the Async Pipe

The Importance of the Async Pipe

We have seen a little of the async pipe already in examples like this:

@Component({
selector: 'app-home',
template: `
<app-greeting [name]="name$ | async"></app-greeting>
`
})
export class HomeComponent {
name$ = of('Josh')
}

We can use it to pull values out of streams and pass them into inputs as above. We can also use it render out values directly in the template:

@Component({
selector: 'app-home',
template: `
<h2 *ngIf="name$ | async as name">{{ name }}</h2>
`
})
export class HomeComponent {
name$ = of('Josh')
}

Or, we can take this a little further and create a single view model vm$ stream that contains all of the data from streams for our entire template:

@Component({
selector: 'app-home',
template: `
<ng-container *ngIf="vm$ | async as vm">
<p>{{ vm.name }}</p>
<p>{{ vm.luckyNumber }}</p>
<p>{{ vm.attempt }}</p>
</ng-container>
`
})
export class HomeComponent {
name$ = of('Josh');
luckyNumber$ = from([5, 22, 587]);
attempts$ = new BehaviorSubject(0);
vm$ = combineLatest([name$, luckyNumber$, attempts$]).pipe(
map(([name, luckyNumber, attempt]) => ({name, luckyNumber, attempt}))
)
}

An important part about the *ngIf syntax above is that this section of the template won’t render until the stream emits and our vm object is actually available to use.

There are three main reasons for using the | async pipe, and we will talk about each separately:

  • The async pipe handles automatically subscribing and unsubscribing for you
  • Once we subscribe to a stream we are no longer coding “reactively”. Using the async pipe encourages us to keep data in streams until they reach their final destination (the template)
  • When a new value is emitted using the async pipe it will trigger change detection, which is important for OnPush change detection

Let’s focus on these points in a little more detail.

The Importance of Unsubscribing

As we have seen, observables can emit multiple values over time. They will just keep emitting these values, and triggering the next handler of the observer, until:

  • It is unsubscribed
  • It errors
  • It triggers the complete notifier

Some observables might just emit one value, some might emit multiple then complete, some might emit values forever and never complete.

This creates the perfect situation for memory leaks. It creates the potential for subscribing to an observable that keeps emitting values over time and not unsubscribing from that without realising that it is still emitting values and doing things. Then maybe the user navigates to the component creating the subscription again, and again, and again, and so on.

This creates a situation where, without us knowing, there is more and more observable subscriptions running in the background slowly consuming our applications memory.

The situations in which not explicitly unsubscribing from an observable is a problem vary — technically, in some situations, it doesn’t really matter. But, it is easy to mistake these situations, and in my opinion it’s not worth dedicating brain power to figuring out which scenarios are safe and which are not.

STANDARD STANDARD

Thanks for checking out the preview of this lesson!

You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).