NgrxStore和Angular - 大量使用异步管道或在构造函数中只订阅一次

时间:2017-01-17 21:56:13

标签: angular ngrx

我开始关注ngrx Store,看到使用Angular异步管道的便利性。同时我不确定是否大量使用Angular异步管道是一个不错的选择。

我举了一个简单的例子。让我们假设在同一模板中我需要显示从商店中检索的对象(例如Person)的不同属性。

一段模板代码可以是

<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个订阅(通过异步管道在模板中创建)到同一个Observable(person$)。

另一种方法是在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>

现在问题

这两种方法在性能方面有什么不同吗?大量使用异步管道(即大量使用订阅)是否会影响代码的效率?

3 个答案:

答案 0 :(得分:37)

两者都不应该将您的应用程序组合为智能和演示组件。

<强>优点:

  • 智能控制器上的所有商品逻辑。
  • 只需一个订阅
  • 复用性
  • 演示控制器只有一个责任,只是提供数据而不知道数据来自何处。 (松散耦合)

回答最后一个问题:

大量使用异步管道会影响效率,因为它会订阅每个异步管道。如果要调用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() {
    }

}

有关详情,请查看:

答案 1 :(得分:12)

另一种可能性是使用这样的结构:

<div *ngIf="person$ | async as per">
    <div>{{ per.name }}</div>
    <div>{{ per.address }}</div>
    <div>{{ per.age }}</div>
<div>

虽然对于可重复使用的代码,但使用表示组件方法可能更好。

请注意这适用于角度5,不确定其他版本。

答案 2 :(得分:11)

您可以在任何可观察声明的末尾添加“.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/