web-dev-qa-db-ja.com

Subject.complete()はすべてのリスナーをサブスクライブ解除しますか?

このメソッドを使用して、簡単な確認ダイアログサービス(Angular 2)を作成します。

confirm(body?: string, title?: string): Subject<void> {
    this.confirmation = new Subject<void>();
    // ... show dialog here... "are you sure?"
    return this.confirmation;
}

_onYesClicked() {
  // ... closing the dialog
  this.confirmation.next();
  this.confirmation.complete();
} 

_onNoClicked() {
  // ... closing the dialog
  this.confirmation.complete();
}

使用法:

confirmationService.confirm().subscribe(() => alert("CONFIRMED"));

誰かがサービスを使用する場合、彼はSubject(Observable)が返され、それに「subscribe()」することができます。サブスクリプションは、「はい」がクリックされたときに呼び出され、確認が行われました...

これは正しい方法ですか?そしてより重要な...への呼び出しは

this.confirmation.complete();

サブスクライブされたリスナーをサブスクライブ解除し、それによって残留参照(メモリリーク)を防ぎますか?

25
Wolfgang

すべてのオブザーバーを確実に削除する場合は、 https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subject.ts#L91 で確認できます。すべてのオブザーバーでcomplete()を呼び出します(オブザーバーは通常、 Observerインターフェイス を実装する単なるダムオブジェクトです)、this.observers.length = 0;を設定します。答えはイエスです。

あなたのアプローチは有効です。Angular2がEventEmitterで定期的に行うのと基本的に同じです。改善できることの1つは、Subjectsを公開するときに asObservable() を使用し始めることです。これは、下でSubjectを使用しているという事実を隠し、通常のObservableのみを返します。この方法では、Subjectnext()complete()、またはerror()を呼び出そうとして、ユーザーが偶然(または誤解)にさせないようにします。

メモリリークについては、RxJSで処理する必要があるため、心配する必要はありません。問題がある場合、作成者はおそらくあなたの前に気づくでしょう。

こちらもご覧ください: Observable vs Subject and asObservable

31
martin