Async Pipe In Angular

Async Pipe In Angular

In this article, we will learn how to use async pipe. The async pipe lets us subscribe to an Observable or Promise from the template and get the value emitted back. When the component loads, the async pipes subscribe to the observable. When the component is destroyed, it unsubscribes. We will go through the syntax and an example using observable, as well as how to use it with ngIf and ngFor. How to share a subscription with the help of ShareReplay. To save the result, use the as operator. It can be used with the httpClient and HTTP get requests, for example.

Syntax of Async Pipe

The async pipe has the following syntax. The result of an expression must be an observable or a promise. The keyword async is followed by the pipe symbol |. With interpolation syntax, we're using the async pipe.

{{expression | async}}

Example

The example below creates an observable. After a delay, it returns 1000. The observable is stored in the obsValue variable.
obsValue = new Observable((observer) => {
  console.log("Observable starts")
  setTimeout(() => { observer.next("90000") }, 1000);
})

It's possible to use it in the template as shown below.
{{ obsValue | async}}

Use the async pipe with ngIf

The async pipe with interpolation is used in the example above. It can also be used with ngIf, ngFor, and other similar functions.

The following example demonstrates how to avoid using the observable directive with the ngIf directive.

When the observable returns a value, the condition (obsValue | async) becomes true. Until then, we will see the elseBlock, which we will use to show the loading indicator. The message Observable is loading is displayed in the example. Please be patient.
<div *ngIf="(obsValue | async); else elseBlock">
  {{ obsValue | async}}
</div>
 
<ng-template #elseBlock>
  Observable is loading. Please wait 
</ng-template>

The ngIf condition becomes true when the observable returns a value, and the pipe shows the returned value.

The following image demonstrates this.

Example of Async Pipe In Angular


The observable fires twice, as you can see in the image above.

We're use the async pipe twice, for example. one inside the if block and the other in the if condition
<div *ngIf="(obsValue | async); else elseBlock"> //obsValue  Subscribed here
  {{ obsValue | async}}        //obsValue  Subscribed here again
</div>

There are two options for resolving this issue. The ShareReplay rxjs operator is one option.

ShareReplay

When you want subscribers to share the observable and access previously emitted values, we use the shareReplay method. i.e. the observable is subscribed only once, and the previously received value is used for further subscriptions.

With shareReplay, the updated observable looks like this. We will have to call in the pipe operator.
obsValue = new Observable((observer) => {
  console.log("Observable starts")
  setTimeout(() => { 
    console.log("Returns value")
    observer.next("1000") 
  }, 5000);
}).pipe(shareReplay());

There are no changes to the component code that are required. However, there is one extra if block in this case. bringing the total number of async pipes to three
<div *ngIf="(obsValue | async); else elseBlock">
  {{ obsValue | async}}
</div>
 
<ng-template #elseBlock>
  Observable is loading. Please wait
</ng-template>
 
<div *ngIf="(obsValue | async);">
  observable has recevied data
</div>

Despite having three subscriptions, the observable is only subscribed once, as shown in the following.


Example of Async Pipe In Angular

Using ngIf “as” syntax

We can save the result in a template local variable by using the as keyword. We may use the result anywhere inside the ngIf block after assigning it to a variable, as seen below.
<div *ngIf="(obsValue | async) as value; else elseBlock">
  {{ value}}      //works only inside the If Block
</div>
 
<ng-template #elseBlock>
  Observable is loading. Please wait
</ng-template>
 
{{ value}}   // will not work 

Check the observable after removing the shareReplay.
obsValue = new Observable((observer) => {
  console.log("Observable starts")
  setTimeout(() => { 
    console.log("Returns value")
    observer.next("1000") 
  }, 5000);
});

Use the async pipe with ngfor


We'll look at how to use the async pipe with ngFor now. In this example, we'll use the httpClient library to make an HTTP get request and use the ngFor library to show the results.

Let's use the free HTTP endpoint https://dog.ceo/dog-api/documentation/ for this example. It gives you an array of hound breeds like the one below (in the message array)
{"message":["afghan","basset","blood","english","ibizan","plott","walker"],"status":"success"}

hounds: Observable<any> = this.getHoundList();
 
getHoundList(): Observable<any> {
  return this.http.get<any>("https://dog.ceo/api/breed/hound/list")
}

To subscribe to the hounds observable, use the (hounds | async) in the template. Isn't it true that we're using a safe navigation operator ? before the message with the property name i.e., it's null at first till the outcome arrives, and without ? Errors will appear in your console.
<ul>
  <li *ngFor="let breed of (hounds | async)?.message">{{breed}}</li>
</ul>

Example of Async Pipe In Angular

You can can use ngIf and ngFor together with the as keyword to save the result in breeds.
<div *ngIf="(hounds | async) as breeds">
  <ul>
    <li *ngFor="let breed of breeds.message">{{breed}}</li>
  </ul> 
</div>

ngIf is used in the following code to display a random image of a dog.

Open app.component.ts file and put the following code:
//component
 
randomPic: Observable<any> = this.getRandom();
 
getRandom(): Observable<any> {
  return this.http.get<any>("https://dog.ceo/api/breeds/image/random")
}


Open app.component.html file and put the following code:
//Template
 
<img src="{{ (randomPic | async)?.message}}">

Conclusion

In this article we learned how to use async pipe. In next article we learn about the how to create custom pipe and how to use it.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in comment section.

Post a Comment

Previous Post Next Post