NgrxStore 和 Angular - 大量使用异步管道或在构造函数中只订阅一次
NgrxStore and Angular - Use the async pipe massively or subscribe just once in the constructor
我开始关注 ngrx Store,我发现使用 Angular 异步管道很方便。同时我不确定大量使用 Angular 异步管道是否是一个好的选择。
我举个简单的例子。假设在同一个模板中,我需要显示从商店检索到的对象(例如一个人)的不同属性。
一段模板代码可以是
<div>{{(person$ | async).name}}</div>
<div>{{(person$ | async).address}}</div>
<div>{{(person$ | async).age}}</div>
而组件 class 构造函数将具有
export class MyComponent {
person$: Observable<Person>;
constructor(
private store: Store<ApplicationState>
) {
this.person$ = this.store.select(stateToCurrentPersonSelector);
}
.....
.....
}
据我所知,这段代码暗示了对同一个 Observable (person$
) 的 3 次订阅(通过异步管道在模板中进行)。
另一种方法是在 MyComponent 中定义 1 个 属性 (person
),并且只有 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>
现在问题
这两种方法在性能方面有什么不同吗?大量使用异步管道(即大量使用订阅)是否会影响代码的效率?
两者都不是,您应该将您的应用程序组合成智能和表示组件。
优点:
- 智能控制器上的所有业务逻辑。
- 订阅一个
- 可重用性
- 展示控制器只有一个职责,只展示数据,不知道数据从哪里来。 (松耦合)
回答最后一个问题:
大量使用async pipe会影响效率,因为它会订阅每一个async pipe。如果您正在调用 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()”添加到任何可观察声明的末尾。然后,可观察对象上的所有异步管道将共享相同的订阅:
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,不确定其他版本。
我开始关注 ngrx Store,我发现使用 Angular 异步管道很方便。同时我不确定大量使用 Angular 异步管道是否是一个好的选择。
我举个简单的例子。假设在同一个模板中,我需要显示从商店检索到的对象(例如一个人)的不同属性。
一段模板代码可以是
<div>{{(person$ | async).name}}</div>
<div>{{(person$ | async).address}}</div>
<div>{{(person$ | async).age}}</div>
而组件 class 构造函数将具有
export class MyComponent {
person$: Observable<Person>;
constructor(
private store: Store<ApplicationState>
) {
this.person$ = this.store.select(stateToCurrentPersonSelector);
}
.....
.....
}
据我所知,这段代码暗示了对同一个 Observable (person$
) 的 3 次订阅(通过异步管道在模板中进行)。
另一种方法是在 MyComponent 中定义 1 个 属性 (person
),并且只有 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>
现在问题
这两种方法在性能方面有什么不同吗?大量使用异步管道(即大量使用订阅)是否会影响代码的效率?
两者都不是,您应该将您的应用程序组合成智能和表示组件。
优点:
- 智能控制器上的所有业务逻辑。
- 订阅一个
- 可重用性
- 展示控制器只有一个职责,只展示数据,不知道数据从哪里来。 (松耦合)
回答最后一个问题:
大量使用async pipe会影响效率,因为它会订阅每一个async pipe。如果您正在调用 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()”添加到任何可观察声明的末尾。然后,可观察对象上的所有异步管道将共享相同的订阅:
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,不确定其他版本。