先週、私はRxJSの答え質問私はについては、別のコミュニティメンバーとの話し合いに入った:「?万一私はすべての特定の副作用のためのサブスクリプションを作成したり、私は一般的にはサブスクリプションを最小限に抑えるために試してみてくださいを」私はmethologyがフル反応性アプリケーションアプローチとき、または一方から他方へ切り替えるようにという観点で使用するかを知りたいです。これはunecesarry議論を避けるために、私と多分他の人を助けます。
セットアップ情報
- すべての例では、活字体であります
- 問題のより良い焦点のサブスクリプションのためのライフサイクル/コンストラクタの無使用量とは無関係の枠組みの中で維持します
- 想像:サブスクリプションは、コンストラクタ/ライフサイクルのinitに追加されます
- 想像:登録解除は破壊ライフサイクルで行われます
副作用(角サンプル)は何ですか
- アップデート/ UIで入力(例
value$ | async
) - コンポーネントの出力/上流(例えば
@Output event = event$
) - 異なる階層上の異なるサービス間Interacton
典型的なユースケース:
- 二つの機能:
foo: () => void; bar: (arg: any) => void
- 二つのソース観測:
http$: Observable<any>; click$: Observable<void>
foo
後に呼び出されhttp$
放出されたとは値を必要としませんbar
後に呼び出されclick$
照射されているが、現在の値が必要http$
ケース:すべての特定の副作用のサブスクリプションを作成します。
const foo$ = http$.pipe(
mapTo(void 0)
);
const bar$ = http$.pipe(
switchMap(httpValue => click$.pipe(
mapTo(httpValue)
)
);
foo$.subscribe(foo);
bar$.subscribe(bar);
ケース:一般的にはサブスクリプションを最小化
http$.pipe(
tap(() => foo()),
switchMap(httpValue => click$.pipe(
mapTo(httpValue )
)
).subscribe(bar);
短期での私自身の意見
私は、サブスクリプションは、あなたが(あなたの観測可能かどうかを共有する)、加入者は、例えばパイプに影響を与えたりべきではない方法を考える必要があるためRxは、最初に、より複雑なランドスケープにするという事実を理解することができます。しかし、より多くのあなたが(より多くのあなたが焦点を当てる:何が起こるとき)あなたのコードを分離容易にそれは将来的には(テスト、デバッグ、更新)あなたのコードを維持することです。このことを念頭に置いて、私は常に単一の観測可能なソースと私のコード内の任意の副作用のために単一のサブスクリプションを作成します。私は、観察まったく同じソースによってトリガされた2件の以上の副作用た場合、私は、観察を共有し、それは別のライフサイクルを持つことができるので、個々の副作用のためにサブスクライブします。
RxJSは、非同期操作を管理するための貴重な資源であり、可能な場合(サブスクリプションの数を減らすことを含む)あなたのコードを簡素化するために使用されるべきです。RxJSアプリケーションでサブスクリプションの全体的な数を減らすことができソリューションを提供する場合も同様に、観測可能では自動的に、その観察可能なサブスクリプションが続くべきではありません。
しかし、厳密に「必要」ではありませんサブスクリプションを作成することが有益であり得る状況があります。
例例外 - 単一のテンプレートでの観測の再利用
あなたの最初の例を見てみると:
// Component:
this.value$ = this.store$.pipe(select(selectValue));
// Template:
<div>{{value$ | async}}</div>
値$は、テンプレートだけで一度使用された場合、私は非同期パイプやコード経済と自動退会について、その利点を活用すると思います。しかしごとにこの答え、テンプレート内の同じ非同期変数への複数の参照は、例えば、避けるべきです。
// It works, but don't do this...
<ul *ngIf="value$ | async">
<li *ngFor="let val of value$ | async">{{val}}</li>
</ul>
このような状況では、私の代わりに別のサブスクリプションを作成して、私のコンポーネントで非非同期変数を更新するためにこれを使用します。
// Component
valueSub: Subscription;
value: number[];
ngOnInit() {
this.valueSub = this.store$.pipe(select(selectValue)).subscribe(response => this.value = response);
}
ngOnDestroy() {
this.valueSub.unsubscribe();
}
// Template
<ul *ngIf="value">
<li *ngFor="let val of value">{{val}}</li>
</ul>
技術的には、それはせずに同じ結果を達成することが可能ですvalueSub
が、アプリケーションの要件は、これは正しい選択であることを意味します。
サブスクライブするかどうかを決定する前に、観察の役割や寿命を考慮すると
一緒になって二つ以上の観測が唯一の使用である場合には、適切なRxJS演算子は、単一のサブスクリプションにそれらを組み合わせるために使用する必要があります。
同様に、もし()最初はすべて除去するために使用されているが、観測可能なの最初の発光は、私が思うの継続的な役割を持っている、観察のためよりも、あなたのコードと回避「余分な」サブスクリプションと経済的であることが大きな理由がありますセッション。
個々の観測のいずれかが独立して、他の有益である場合、別のサブスクリプション(S)の柔軟性と透明性は考慮に値するかもしれません。そうする明確な理由がない限りしかし、私の最初の声明に従って、サブスクリプションは自動的に、すべての観測可能なために作成すべきではありません。
Unsubscriptionsについて:
ポイントに対する追加のサブスクリプションは、より多くのことですunsubscriptionsが必要とされています。あなたが言ったように、我々はすべての必要なunsubscriptionsはonDestroyを適用することを前提としていたいのですが、本当の人生は常にスムーズにそれを行っていません!再び、RxJSは便利なツールを提供する(例えば、最初の() )コードを簡素化し、メモリリークの可能性を減少させるこのプロセスを、合理化します。この記事では、価値があり得る関連さらなる情報および例を提供します。
個人的な好み/冗長対簡潔:
アカウントにあなた自身の好みを取るようにしてください。私は、コードの冗長性に関する一般的な議論に向けて迷走する必要はありませんが、その目的は、あまりにも多くの「ノイズ」とあなたのコードが過度に不可解な作りの適切なバランスを見つけるためにする必要があります。これは一見の価値があるかもしれません。