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:
Thanks!
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.
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.
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.
Observables are "lazy", meaning if no one is listening, nothing happens.
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:
myObservable$
is readyThere'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()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With