takeUntilRxJSオペレーターを使用してサブスクリプションを宣言的に管理する方法
序章
Angularは、HTTPサービスから返されたサブスクリプションのように、または非同期パイプを使用している場合に、監視可能なサブスクリプションからのサブスクリプション解除を処理します。 ただし、他の状況では、すべてのサブスクリプションを管理し、長期間有効なサブスクリプションから確実にサブスクリプションを解除することがすぐに困難になる可能性があります。 ほとんどのサブスクリプションからサブスクライブを解除するポリシーにも、独自の問題があります。
この記事では、手動でサブスクライブおよびサブスクライブ解除することに依存するAngularアプリケーションの例を紹介します。 次に、takeUntil
演算子を使用してサブスクリプションを宣言的に管理するAngularアプリケーションの例と比較します。
前提条件
この記事をフォローしたい場合は、次のものが必要になります。
- RxJSライブラリ、特に
Observable
とSubscription
にある程度精通していると有益です。 - ApolloとGraphQLにある程度精通していると役立ちますが、必須ではありません。
このチュートリアルは、ノードv15.3.0、npm
v6.14.9、@angular/core
v11.0.4、rxjs
v6.6.3、apollo-angular
v2.1.0、 graph-tag
v2.11.0。 この記事は、@angular/core
およびrxjs
の以前のバージョンからの移行における変更を反映するように編集されました。
手動で退会する
2つのサブスクリプションから手動でサブスクリプションを解除する例から始めましょう。
この例では、コードは Apollo watchQuery にサブスクライブして、GraphQLエンドポイントからデータを取得しています。
このコードは、onStartInterval
メソッドが呼び出されたときにサブスクライブする監視可能な間隔も作成しています。
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription, interval } from 'rxjs';
import { Apollo } from 'apollo-angular';
import gql from 'graphql-tag';
@Component({ ... })
export class AppComponent implements OnInit, OnDestroy {
myQuerySubscription: Subscription;
myIntervalSubscription: Subscription;
constructor(private apollo: Apollo) {}
ngOnInit() {
this.myQuerySubscription = this.apollo.watchQuery<any>({
query: gql`
query getAllPosts {
allPosts {
title
description
publishedAt
}
}
`
})
.valueChanges
.subscribe(({data}) => {
console.log(data);
});
}
onStartInterval() {
this.myIntervalSubscription = interval(250).subscribe(value => {
console.log('Current value:', value);
});
}
ngOnDestroy() {
this.myQuerySubscription.unsubscribe();
if (this.myIntervalSubscription) {
this.myIntervalSubscription.unsubscribe();
}
}
}
ここで、コンポーネントに多くの同様のサブスクリプションがあると想像してください。コンポーネントが破棄されたときにすべてがサブスクライブ解除されるようにするためのかなりのプロセスになる可能性があります。
takeUntil
で宣言的にサブスクライブを解除する
解決策は、takeUntil
演算子を使用してサブスクリプションを作成し、ngOnDestroy
ライフサイクルフックで真の値を発行するサブジェクトを使用することです。
次のスニペットはまったく同じことを行いますが、今回はコードが宣言的にサブスクライブを解除します。 追加の利点は、サブスクリプションへの参照を保持する必要がなくなったことです。
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject, interval } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Apollo } from 'apollo-angular';
import gql from 'graphql-tag';
@Component({ ... })
export class AppComponent implements OnInit, OnDestroy {
destroy$: Subject<boolean> = new Subject<boolean>();
constructor(private apollo: Apollo) {}
ngOnInit() {
this.apollo.watchQuery<any>({
query: gql`
query getAllPosts {
allPosts {
title
description
publishedAt
}
}
`
})
.valueChanges
.pipe(takeUntil(this.destroy$))
.subscribe(({data}) => {
console.log(data);
});
}
onStartInterval() {
interval(250)
.pipe(takeUntil(this.destroy$))
.subscribe(value => {
console.log('Current value:', value);
});
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.unsubscribe();
}
}
手動でサブスクライブを解除する代わりにtakeUntil
のような演算子を使用すると、オブザーバブルも完了し、オブザーバブルで完了イベントがトリガーされることに注意してください。
コードをチェックして、意図しない副作用が発生しないことを確認してください。
結論
この記事では、takeUntil
を使用して宣言的にサブスクライブを解除する方法について学習しました。 不要なサブスクリプションのサブスクリプションを解除すると、メモリリークの防止に役立ちます。 宣言的にサブスクリプションを解除すると、サブスクリプションへの参照を必要としないようになります。
take
、takeWhile
、first
など、他にも同様のRxJS演算子があり、これらはすべて監視可能オブジェクトを完成させます。
Angularについて詳しく知りたい場合は、Angularトピックページで演習とプログラミングプロジェクトを確認してください。