---編集4-追加リソース(2018/09/01)
Angularのアドベンチャーの最近のエピソードで、 Ben LeshとWard Bellが、コンポーネントでサブスクライブを解除する方法/時期に関する問題について話し合っています。議論は1:05:30頃に始まります。
ワードは言及しright now there's an awful takeUntil dance that takes a lot of machinery
、シャイ・レズニックは言及しますAngular handles some of the subscriptions like http and routing
。
これに対してベンは、ObservableがAngularコンポーネントのライフサイクルイベントにフックできるようにするためのディスカッションがあることを述べ、Wardは、コンポーネントの内部状態として維持されるObservableをいつ完了するかを知る方法として、コンポーネントがサブスクライブできるライフサイクルイベントのObservableを提案しています。
そうは言っても、私たちは今ほとんど解決策を必要としているので、ここにいくつかの他のリソースがあります。
takeUntil()
RxJのコアチームメンバーであるニコラスジェイミソンからのパターンの推奨と、パターンの実施を支援するtslintルール。https://ncjamieson.com/avoiding-takeuntil-leaks/
コンポーネントインスタンス(this
)をパラメーターとして取り、中に自動的にサブスクライブ解除するObservableオペレーターを公開する軽量npmパッケージngOnDestroy
。
https://github.com/NetanelBasal/ngx-take-until-destroy
上記の別のバリエーションで、AOTビルドを行わない場合のエルゴノミクスが若干改善されています(ただし、今はすべてAOTを行う必要があります)。
https://github.com/smnbbrv/ngx-rx-collector
*ngSubscribe
非同期パイプのように機能するが、テンプレートに埋め込みビューを作成するカスタムディレクティブ。これにより、テンプレート全体で「ラップされていない」値を参照できます。
https://netbasal.com/diy-subscription-handling-directive-in-angular-c8f6e762697f
NicholasのブログへのコメントtakeUntil()
で、コンポーネントの過剰使用はコンポーネントがやりすぎていることを示している可能性があり、既存のコンポーネントを機能コンポーネントとプレゼンテーションコンポーネントに分離することを検討する必要があることを述べています。次に| async
、ObservableをFeatureコンポーネントからInput
Presentationalコンポーネントのに追加できます。つまり、サブスクリプションはどこにも必要ありません。このアプローチの詳細については、こちらをご覧ください
---編集3-「公式」ソリューション(2017/04/09)
私はNGConfでこの質問についてウォードベルと話しました(彼が正しいと言ったこの答えを彼にも示しました)と彼は私にAngularのドキュメントチームが公開されていないこの質問の解決策を持っていると言いました(承認を得るために取り組んでいますが) )。彼はまた、私がSOの回答を次の公式勧告で更新できると私に言った。
今後使用する必要があるソリューションは、クラスコード内でへの呼び出しをprivate ngUnsubscribe = new Subject();
持つすべてのコンポーネントにフィールドを追加することです。.subscribe()
Observable
次にthis.ngUnsubscribe.next(); this.ngUnsubscribe.complete();
、ngOnDestroy()
メソッドを呼び出します。
(@metamakerですでに述べたように)秘密のソースは、takeUntil(this.ngUnsubscribe)
各呼び出しの前に呼び出す.subscribe()
ことで、コンポーネントが破棄されたときにすべてのサブスクリプションがクリーンアップされることを保証します。
例:
import { Component, OnDestroy, OnInit } from '@angular/core';
// RxJs 6.x+ import paths
import { filter, startWith, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { BookService } from '../books.service';
@Component({
selector: 'app-books',
templateUrl: './books.component.html'
})
export class BooksComponent implements OnDestroy, OnInit {
private ngUnsubscribe = new Subject();
constructor(private booksService: BookService) { }
ngOnInit() {
this.booksService.getBooks()
.pipe(
startWith([]),
filter(books => books.length > 0),
takeUntil(this.ngUnsubscribe)
)
.subscribe(books => console.log(books));
this.booksService.getArchivedBooks()
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(archivedBooks => console.log(archivedBooks));
}
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
}
注:takeUntil
演算子チェーンの中間オブザーバブルでのリークを防ぐために、演算子を最後の演算子として追加することが重要です。
---編集2(2016/12/28)
ソース5
Angularチュートリアルのルーティングの章では、次のように述べられています。ルートパラメータObservable。」- マーク・ライコック
これはルーターオブザーバブルに関するAngularドキュメントのGithubの問題に関するディスカッションであり、Ward Bellはこれらすべての明確化が作業中であると述べています。
---編集1
ソース4
NgEuropeからのこのビデオでは、 Rob Wormaldがルーターオブザーバブルの登録を解除する必要がないことも述べています。彼はまた、http
サービスとActivatedRoute.params
このビデオで2016年11月から言及しています。
---元の回答
TLDR:
この質問には(2)種類ありますObservables
-有限値と無限値があります。
http
Observables
作物 有限(1)の値とDOMのようなものをevent listener
Observables
生み出す無限の値を。
手動で呼び出す場合 subscribe
(非同期パイプを使用せずに)はunsubscribe
、infinite からObservables
。
有限のものについて心配しないでくださいRxJs
、それらの世話をします。
ソース1
私は角度のギッターにロブWormaldから答えを突き止め、ここ。
彼は述べています(私は明確にするために再編成され、強調は私のものです)
その単一値シーケンス(httpリクエストのような)の場合、手動クリーンアップが不要です(手動コントローラに加入と仮定)
「それが完了するシーケンスなら(うちの1つの値のシーケンス、http、laは1つです)
その無限列ならば、あなたは解除すべきです非同期パイプがあなたのためにしています
また、彼はObservablesに関するこのyoutubeビデオでthey clean up after themselves
... Observables のコンテキストで言及しています(Promiseのcomplete
ように、常に1つの値を生成して終了するため、常に完了します-確実にクリーンアップするために、Promiseからの登録解除を心配していませんxhr
イベントリスナーですよね?)
ソース2
また、中角度2にRangleガイドそれは読み込み
ほとんどの場合、早期にキャンセルするか、Observableのサブスクリプションよりも寿命が長い場合を除き、unsubscribeメソッドを明示的に呼び出す必要はありません。Observableオペレーターのデフォルトの動作は、.complete()または.error()メッセージがパブリッシュされるとすぐにサブスクリプションを破棄することです。RxJSはほとんどの場合「ファイアアンドフォーゲット」方式で使用されるように設計されていることに注意してください。
フレーズはいつ our Observable has a longer lifespan than our subscription
はいつ適用されますか?
これは、サブスクリプションがコンポーネントの内部で作成されたときに適用されますObservable
。
これを、http
10個の値を発行するリクエストまたはオブザーバブルにサブスクライブし、そのhttp
リクエストが返される前にコンポーネントが破棄されるか、10個の値が発行される場合でも、これは意味があると読みました。
リクエストが返されるか、10番目の値が最終的に発行されると、Observable
は完了し、すべてのリソースがクリーンアップされます。
ソース3
私たちが見れば、この例と同じRangleから我々がいることがわかります導くSubscription
にはroute.params
必要ないunsubscribe()
ものはときに我々は知らないので、params
変更(新しい値を放出する)を停止します。
離れてナビゲートするとコンポーネントが破壊される可能性があります。その場合、ルートパラメータは引き続き変更される可能性が高く(アプリが終了するまで技術的に変更される可能性があります)、サブスクリプションに割り当てられたリソースは割り当てられませんcompletion
。
Subscription
shttp-requests
はonNext
1回だけ呼び出してからを呼び出すため、無視できると思いますonComplete
。Router
代わりに呼び出し、onNext
繰り返し呼び出すことがないかもしれませんonComplete
(いないことを確認...そのことについて)。同じことがObservable
sからEvent
sにも当てはまります。だから私はそれらがそうあるべきだと思いますunsubscribed
。