RxJS公式ドキュメントにも書いていない!BehaviorSubjectとObservableの秘密
RxJS:BehaviorSubjectとObservableの違い
データ配信
- Observable: 購読者が登録した時点からデータ配信を開始します。過去に発行されたデータは受け取れません。
- BehaviorSubject: 購読者が登録した時点だけでなく、直前の最新値も配信します。
例:
const observable = Rx.Observable.interval(1000);
observable.subscribe(value => console.log(value)); // 1秒ごとに値が出力
setTimeout(() => {
observable.subscribe(value => console.log('遅延購読:', value)); // 購読開始時点からのみ値が出力
}, 3000);
対してBehaviorSubject:
const subject = new Rx.BehaviorSubject(0);
subject.subscribe(value => console.log(value)); // 0が出力
subject.next(1); // 1が出力
setTimeout(() => {
subject.subscribe(value => console.log('遅延購読:', value)); // 1が出力
}, 3000);
状態管理
- Observable: データストリームそのもののみを表します。状態管理は外部で行う必要があります。
- BehaviorSubject: 内部的に最新値を保持し、状態管理を担います。
const observable = Rx.Observable.fromEvent(document, 'click');
let count = 0;
observable.subscribe(() => {
count++;
console.log(count);
});
クリック回数を表示したい場合、count変数を外部で管理する必要があります。
const subject = new Rx.BehaviorSubject(0);
subject.subscribe(value => console.log(value));
document.addEventListener('click', () => {
subject.next(++subject.getValue()); // 内部で状態管理
});
ユースケース
- Observable: データストリームそのものを扱う場合に適しています。
- BehaviorSubject: 以下のユースケースに適しています。
- 最新値を常に保持したい場合
- 状態管理を簡略化したい場合
- 複数のコンポーネント間でデータ共有したい場合
- Observable: データストリーム配信に特化
状況に応じて使い分けることが重要です。
ObservableとBehaviorSubjectの比較
// Observable
const observable = Rx.Observable.interval(1000);
observable.subscribe(value => console.log('Observable:', value)); // 1秒ごとに値が出力
setTimeout(() => {
observable.subscribe(value => console.log('Observable 遅延購読:', value)); // 購読開始時点からのみ値が出力
}, 3000);
// BehaviorSubject
const subject = new Rx.BehaviorSubject(0);
subject.subscribe(value => console.log('BehaviorSubject:', value)); // 0が出力
subject.next(1); // 1が出力
setTimeout(() => {
subject.subscribe(value => console.log('BehaviorSubject 遅延購読:', value)); // 1が出力
}, 3000);
Observable: 1
Observable: 2
Observable: 3
Observable 遅延購読: 3
BehaviorSubject: 0
BehaviorSubject: 1
BehaviorSubject 遅延購読: 1
BehaviorSubjectを使った状態管理
const subject = new Rx.BehaviorSubject(0);
subject.subscribe(value => console.log(value));
document.addEventListener('click', () => {
subject.next(++subject.getValue()); // 内部で状態管理
});
実行結果
0
1
2
3
...
クリックするたびに、subject
の最新値が1ずつ増加し、コンソールに出力されます。
BehaviorSubjectとObservableの代替案
状態管理に特化したライブラリを使用するのも一つの方法です。代表的なライブラリは以下の通りです。
- NgRx Store: Angularアプリケーション向け
- Redux: JavaScript汎用
これらのライブラリは、状態管理を簡略化し、コードをより分かりやすくすることができます。
自作のSubject
特定のユースケースに特化したSubjectを作成することも可能です。例えば、以下のユースケースの場合:
- 最新値のみを保持したい場合:
ReplaySubject(1)
- 過去一定期間のデータのみを保持したい場合:
WindowSubject
これらのSubjectは、BehaviorSubject
よりもメモリ使用量を抑えることができます。
シンプルなデータの場合は変数
データ量が少なく、複雑な処理を行わない場合は、単純な変数で管理することも可能です。
その他のObservable
BehaviorSubject
以外にも、Observable
には様々な種類があります。状況に応じて使い分けることで、コードをより効率的にすることができます。
BehaviorSubject
は、データストリーム配信と状態管理を兼ね備えた便利な型です。しかし、状況によっては他の方法の方が適している場合があります。
javascript angular rxjs