【问题标题】:NgrxStore and Angular - Use the async pipe massively or subscribe just once in the constructorNgrxStore 和 Angular - 大量使用异步管道或在构造函数中只订阅一次
【发布时间】:2017-06-02 03:23:05
【问题描述】:

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

我举一个简单的例子。假设在同一个模板中,我需要显示从 Store 中检索到的对象(例如 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>

现在的问题

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

【问题讨论】:

标签: angular ngrx


【解决方案1】:

您也不应该将您的应用程序编写为智能和演示组件。

优点:

  • 智能控制器上的所有业务逻辑。
  • 只需订阅一次
  • 可重用性
  • 展示控制器只有一个职责,只展示数据,不知道数据从哪里来。 (松散耦合)

回答最后一个问题:

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

}

更多信息请查看:

【讨论】:

  • 我很欣赏拆分智能组件和演示组件的价值。出于您提到的所有原因,这很有意义。如果我们只看故事的“代码效率”方面,我是否正确地假设使用一个“异步管道”和许多“属性绑定”比使用“许多异步管道”更有效?提前谢谢
  • 与我想要询问的信息完全相同。非常感谢!
  • 很好的答案,但是在使用带有路由器的子组件时它会有什么用处?
【解决方案2】:

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

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

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

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

【讨论】:

  • 我喜欢这个,因为它将智能和演示组件融合到一个代码块中。出于完全相同的原因,我不喜欢这个。 :)
  • 如何在控制器中访问per?我猜现在的方式?
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 2021-06-09
    • 2020-11-13
    • 1970-01-01
    • 2019-05-06
    • 2016-12-25
    • 2021-11-04
    • 2021-07-05
    • 2019-04-21
    • 2017-11-30
    相关资源
    最近更新 更多