SubjectとBehaviorSubjectの違い
Angular, TypeScript, RxJS での Subject と BehaviorSubject の違い
Subject と BehaviorSubject は、RxJS でイベントストリームを扱うための重要な概念です。どちらも Observable のサブタイプであり、値をエミットすることができます。しかし、その振る舞いには重要な違いがあります。
Subject
- 多次元ブロードキャスト
複数の購読者が同じ Subject を購読すると、各購読者は購読後のエミットされた値のみを受け取ります。 - 過去の値は保持しない
購読後にエミットされた値のみが購読者に配信されます。 - 初期値を持たない
Subject は、購読されるまで値をエミットしません。
コード例
import { Subject } from 'rxjs';
const subject = new Subject<number>();
subject.subscribe(value => console.log('Observer A:', value));
subject.next(1); // Observer A: 1
subject.subscribe(value => console.log('Observer B:', value));
subject.next(2); // Observer A: 2, Observer B: 2
BehaviorSubject
- 過去の値を保持する
購読時に最新の値がすぐに配信されます。 - 初期値を持つ
BehaviorSubject は、作成時に初期値を指定します。
import { BehaviorSubject } from 'rxjs';
const behaviorSubject = new BehaviorSubject<number>(0);
behaviorSubject.subscribe(value => console.log ('Observer A:', value)); // Observer A: 0
behaviorSubject.next(1); // Observer A: 1
behaviorSubject.subscribe(value => console.log('Observer B:', value)); // Observer B: 1
- BehaviorSubject
購読時に最新の値を配信し、過去の値も保持する、初期値を持つ Observable。 - Subject
購読後にエミットされた値のみを配信する、初期値を持たない Observable。
Subject と BehaviorSubject のコード例解説
Subject のコード例
import { Subject } from 'rxjs';
const subject = new Subject<number>();
subject.subscribe(value => console.log('Observer A:', value));
subject.next(1); // Observer A: 1
subject.subscribe(value => console.log('Observer B:', value));
subject.next(2); // Observer A: 2, Observer B: 2
- Subject の作成
new Subject<number>()
で、数値をエミットする Subject を作成します。
Observable.create()
- 複雑性
手動で購読管理やエラー処理を行う必要があるため、実装が複雑になることがあります。 - 柔軟性
任意のロジックを実装できるため、複雑なシナリオに対応できます。 - 直接的な Observable の作成
Observable.create()
を使用して、Observable を直接作成し、購読者に値をエミットするロジックを記述することができます。
import { Observable } from 'rxjs';
const observable = new Observable<number>(observer => {
// 購読時の処理
observer.next(1);
observer.next(2);
observer.complete();
});
observable.subscribe(value => console.log(value));
ReplaySubject
- メモリ消費
多くの過去の値を保存する場合は、メモリ消費に注意が必要です。 - バッファリング
過去の値をバッファリングすることで、購読者が遅延した場合でも、最新の値を取得できます。 - 過去の値の保存
ReplaySubject
は、指定されたウィンドウサイズ内の過去の値を保存し、新しい購読者に配信します。
import { ReplaySubject } from 'rxjs';
const replaySubject = new ReplaySubject<number>(2);
replaySubject.next(1);
replaySubject.next(2);
replaySubject.next(3);
replaySubject.subscribe(value => console.log(value)); // 2, 3
AsyncSubject
- 遅延
購読が完了するまで値を配信しないため、遅延が生じる可能性があります。 - 非同期処理
非同期処理の完了結果を通知する際に有用です。 - 最後の値のみ
AsyncSubject
は、最後のエミットされた値のみを配信し、購読が完了した後にその値をエミットします。
import { AsyncSubject } from 'rxjs';
const asyncSubject = new AsyncSubject<number>();
asyncSubject.next(1);
asyncSubject.next(2);
asyncSubject.subscribe(value => console.log(value)); // 2
カスタム Observable
- 独自の振る舞い
必要に応じて、独自の Observable を作成し、特定のロジックを実装することができます。
import { Observable } from 'rxjs';
const customObservable = new Observable<number>(observer => {
// カスタムのロジックを実装
observer.next(1);
setTimeout(() => {
observer.next(2);
observer.complete();
}, 1000);
});
customObservable.subscribe(value => console.log(value));
angular typescript rxjs