NgrxStore и Angular - используйте асинхронный канал массово или подпишитесь только один раз в конструкторе
Я начинаю смотреть на ngrx Store и вижу удобство использования угловой асинхронной трубы. В то же время я не уверен, что массовое использование угловой асинхронной трубы является хорошим выбором.
Я сделаю простой пример. Предположим, что в одном и том же шаблоне мне нужно показать разные атрибуты объекта (например, человека), который извлекается из хранилища.
Фрагмент кода шаблона может быть
<div>{{(person$ | async).name}}</div>
<div>{{(person$ | async).address}}</div>
<div>{{(person$ | async).age}}</div>
В то время как конструктор класса компонента будет есть
export class MyComponent {
person$: Observable<Person>;
constructor(
private store: Store<ApplicationState>
) {
this.person$ = this.store.select(stateToCurrentPersonSelector);
}
.....
.....
}
Насколько я понимаю, этот код подразумевает 3 подписки (сделанные в шаблоне через асинхронный канал) на одну и ту же наблюдаемую (
person$).Альтернативой было бы определить 1 свойство (person) в MyComponent и иметь только 1 подписку (в конструкторе), которая заполняет свойство, например
export class MyComponent {
person: Person;
constructor(
private store: Store<ApplicationState>
) {
this.store.select(stateToCurrentPersonSelector)
.subscribe(person => this.person = person);
}
.....
.....
}
В то время как шаблон использует стандартную привязку свойств (т. е. без асинхронного канала), например
<div>{{person.name}}</div>
<div>{{person.address}}</div>
<div>{{person.age}}</div>
ТЕПЕРЬ ВОПРОС
Есть ли какие-либо разница в показателях эффективности между двумя подходами? Повлияет ли массовое использование асинхронного канала (т. е. массовое использование подписок) на эффективность кода?
Спасибо заранее за любое руководство
3 ответов:
Ни то, ни другое, вы должны составлять свое приложение как интеллектуальные и презентационные компоненты.
Преимущества:
- вся логика работы на интеллектуальном контроллере.
- только одна подписка
- возможность повторного использования
Контролер представления имеет только одну обязанность, только представлять данные и не знает, откуда эти данные берутся. (слабо связанные)Отвечая на последний вопрос:
Массовое использование асинхронной трубы приведет к влияет на эффективность, потому что он будет подписываться на каждый асинхронный канал. Вы можете заметить это больше, если вы вызываете службу http, потому что она вызовет запрос http для каждого канала асинхронности.
Умный Компонент
@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); } }Компонент Представления
@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() { } }Для получения дополнительной информации чек:
Вы можете добавить ".share () " до конца любых наблюдаемых деклараций. Все ваши асинхронные каналы на observable будут использовать одну и ту же подписку:
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 демонстрация: https://embed.plnkr.co/HNuq1jUh3vyfR2IuIe4X/
Другая возможность заключается в использовании конструкции, подобной этой:
<div *ngIf="person$ | async as per"> <div>{{ per.name }}</div> <div>{{ per.address }}</div> <div>{{ per.age }}</div> <div>Хотя для многократно используемых битов кода возможно лучше использовать метод компонента представления.
Обратите внимание, что это работает в angular 5, не уверен насчет других версий.
Comments