3d cartoon hands holding a phone

Unlock full course by purchasing a membership

Lesson 6

The Importance of the Async Pipe

Time to meet your new best friend

STANDARD

The Importance of the Async Pipe

We have spent a lot of time talking about subscribing to observables, and even pointing out how an observable stream won’t actually even do anything until you subscribe to it. Given that, the advice I am going to give you in this lesson might seem a little odd:

Avoid subscribing as much as possible!

Perhaps I should phrase that as avoid subscribing as much as practical. We do still need to subscribe to observables in order to get them to do anything, but wherever possible we are going to use the async pipe to do the subscribing for us.

We have seen this a little already:

@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, as we have seen recently, 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. Later we will see more advanced examples where we display an alternative loading template if the stream has not emitted yet.

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:

STANDARD
Key

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