I am starting to look at ngrx Store and I see the convenience to use the Angular async pipe. At the same time I am not sure whether using the Angular async pipe massively is a good choice.
I make a simple example. Let's assume that in the same template I need to show different attributes of an object (e.g. a Person) which is retrieved from the Store.
A piece of template code could be
<div>{{(person$ | async).name}}</div>
<div>{{(person$ | async).address}}</div>
<div>{{(person$ | async).age}}</div>
while the component class constructor would have
export class MyComponent {
person$: Observable<Person>;
constructor(
private store: Store<ApplicationState>
) {
this.person$ = this.store.select(stateToCurrentPersonSelector);
}
.....
.....
}
As far as I understand this code implies 3 subscriptions (made in the template via the async pipe) to the same Observable (person$
).
An alternative would be to define 1 property (person
) in MyComponent and to have only 1 subscription (in the constructor) that fills the property, such as
export class MyComponent {
person: Person;
constructor(
private store: Store<ApplicationState>
) {
this.store.select(stateToCurrentPersonSelector)
.subscribe(person => this.person = person);
}
.....
.....
}
while the template uses standard property binding (i.e. without the async pipe), such as
<div>{{person.name}}</div>
<div>{{person.address}}</div>
<div>{{person.age}}</div>
Now the question
Is there any difference in terms of performance between the 2 approaches? Is the massive use of async pipe (i.e. a massive use of subscriptions) going to affect the efficiency of the code?
The async pipe allows us to subscribe to an Observable or Promise from the template and returns the value emitted. The async pipes subscribe to the observable when the component loads. It unsubscribes when the component gets destroyed. In this tutorial we will show you how to use async pipe.
The async pipe allows us to subscribe to an Observable or Promise from the template and returns the value emitted. The async pipes subscribe to the observable when the component loads. It unsubscribes when the component gets destroyed.
Leverage the power of Angular components and Angular async pipe to code without asynchronously, Use libraries like reselect, rxjs to manipulate observable, Make sure the external variables used inside the Rx operators function are const. First, to understand the context, we need to understand what is observable.
In the same way we can use the async pipe with the ngIf directive, we can use it with the ngFor directive. To do that, the observable has to resolve to an array type, not just a single value.
Neither, you should compose your application as smart and presentation components.
Advantages:
Answering the last question:
The massive use of async pipe will affect the efficiency, because it will subscribe to every async pipe. You can notice this more if you are calling a http service, because it will call the http request for each async pipe.
Smart Component
@Component({
selector: 'app-my',
template: `
<app-person [person]="person$ | async"></app-person>
`,
styleUrls: ['./my.component.css']
})
export class MyComponent implements OnInit {
person$: Observable<Person>;
constructor(private store: Store<ApplicationState>) {}
ngOnInit() {
this.person$ = this.store.select(stateToCurrentPersonSelector);
}
}
Presentation Component
@Component({
selector: 'app-person',
template: `
<div>{{person.name}}</div>
<div>{{person.address}}</div>
<div>{{person.age}}</div>
`,
styleUrls: ['./my.component.css']
})
export class PersonComponent implements OnInit {
@Input() person: Person;
constructor() {}
ngOnInit() {
}
}
For more info check:
Another possibility is to use construction like this:
<div *ngIf="person$ | async as per">
<div>{{ per.name }}</div>
<div>{{ per.address }}</div>
<div>{{ per.age }}</div>
<div>
Although for reusable bits of code its possibily better to use presentation component method.
Please note this works in angular 5, not sure about other versions.
You can add ".share()" to the end of any observable declarations. All of your async pipes on an observable will then share the same subscription:
this.name$ = Observable.create(observer => {
console.log("Subscriber!", observer);
return observer.next("john")
}).delay(2000).share();
this.httpget$ = http.get("https://api.github.com/").share();
Plunkr demonstrating: https://embed.plnkr.co/HNuq1jUh3vyfR2IuIe4X/
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