Yesterday, we looked at the pros and cons of our first code example.
Today, let’s cover the pros and cons of our second example:
Example #2 – Observable
<div *ngFor="let data of getData() | async">{{data.name}}</div>
This code is calling a method in a template, too, and that’s a lot worse than in example #1. Here’s why: If the getData()
method returns an Observable by calling httpClient.get()
(or a service that makes that same call) then the async pipe subscribes to it and receives the data, which triggers change detection, so Angular calls getData() again, gets a new Observable, the async pipe subscribes to it, and there you have an infinite loop of HTTP requests that will bring down your browser for sure, and possibly your server.
How to fix it?
<div *ngFor="let data of data$ | async">
Store the Observable in a variable instead of calling a method, and the problem is solved. You can assign that Observable in the constructor of your component as follows:
constructor(service: DataService) {
this.data$ = servie.getData();
}
Code language: JavaScript (javascript)
At this point the code is pretty much optimal because:
- We have automatic subscription and unsubscription thanks to the async pipe
- No method is called in the template
The only con is the async pipe syntax and working with Observables, which is often considered the most complex part of the Angular learning curve.