web-dev-qa-db-ja.com

NgrxStoreおよびAngular-非同期パイプを大量に使用するか、コンストラクターで1回だけサブスクライブします

私はngrxストアを調べ始めており、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);
  }
.....
.....
}

私が理解している限り、このコードは同じ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>

今の質問

2つのアプローチの間にパフォーマンスの点で違いはありますか?非同期パイプの大規模な使用(つまり、サブスクリプションの大規模な使用)は、コードの効率に影響しますか?

44
Picci

どちらも、アプリケーションをスマートコンポーネントおよびプレゼンテーションコンポーネントとして構成する必要はありません。

利点:

  • スマートコントローラー上のすべてのビジネスロジック。
  • ただ1つのサブスクライブ
  • 再利用性
  • プレゼンテーションコントローラーの役割は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() {
    }

}

詳細情報の確認:

37
Victor Godoy

別の可能性は、次のような構成を使用することです。

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

コードの再利用可能なビットの場合は、プレゼンテーションコンポーネントメソッドを使用することをお勧めします。

これはangular 5で動作することに注意してください。他のバージョンについてはわかりません。

12
marxin

監視可能な宣言の最後に「.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/

11
John Hamm