Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - Observable with async pipe used multiple times in template... Good Practice or Bad?

If I have the need to bind multiple properties from the same observable within my component template...

For example:

<my-random-component[id]="(myObservable$ | async).id"> ... <my-random-component2[name]="(myObservable$ | async).name"> 

...am I better off doing it like I have above (which I see a lot), or is it more efficient to subscribe to my observable inside my .ts file, set a single object variable, and then bind to that? The idea with the latter approach being that the observable will only be called once.

Questions:

  1. Does the observable in the above code get called each time it is used via | async?
  2. Does the compiler do any efficiency magic behind the scenes to only call the observable once even if used 10 times w/in my template?
  3. Which approach is better/preferred?

Thanks!

like image 694
Mark Avatar asked Oct 10 '18 22:10

Mark


People also ask

Should I use async pipe?

Any Angular developer worth his salt has gotta admit that the AsyncPipe is quite terrific. If you subscribe() to an Observable or Promise you'll need to unsubscribe() at the end of your component's life cycle to avoid memory leaks. Change detection works splendidly with the async pipe.

Why async pipe is impure?

Because of the way Promise s work, Angular's async pipe has to be impure (meaning that it can return different outputs without any change in input). The transform method on Pipe s is synchronous, so when an async pipe gets a Promise , the pipe adds a callback to the Promise and returns null.

Does async pipe automatically unsubscribe?

The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted. When a new value is emitted, the async pipe marks the component to be checked for changes. When the component gets destroyed, the async pipe unsubscribes automatically to avoid potential memory leaks.

Why Observable is lazy?

Observables are "lazy", meaning if no one is listening, nothing happens.


1 Answers

Using the async pipe makes handling subscriptions much easier. It automatically handles unsubscribing unlike subscribing in the component.

That said, there is a better pattern than what the example is showing. Rather than having multiple async calls on components, you can write it 2 different ways. I'm assuming these components are in the same template file:

    <div *ngIf="(myObservable$ | async) as myObservable">       <my-random-component [id]="myObservable.id">       <my-random-component2 [name]="myObservable.name">     </div> 

Wrapping the code in ngIf does 2 things:

  • It cuts down on duplicate code
  • The components do not exist until myObservable$ is ready

There's also one more idea if you want to stick with calling async every single time:

    // COMPONENT     name$: Observable<string>;     id$: Observable<string>;          ngOnInit() {         // Return the exact value you want rather than the full object              this.name$ = OBSERVABLE_SOURCE         .pipe(             map(res => res.name)         );              this.id$ = OBSERVABLE_SOURCE         .pipe(             map(res => res.id)         );     } 
    // TEMPLATE     <my-random-component [id]="(id$ | async)">     <my-random-component2 [name]="(name$ | async)"> 

Pipes do not automatically run without a subscription. You can map, tap, or do anything else you want with it and it will not run until you add async/.subscribe().

like image 186
austinthedeveloper Avatar answered Sep 24 '22 09:09

austinthedeveloper