サンプルコードで学ぶObservableとSubjectの実践例
RxJSにおけるObservableとSubjectの違い
Observableは、時間経過とともに値を発行するデータストリームを表します。データソースからのイベント通知、センサーデータの読み取り、APIからのレスポンスなど、様々なユースケースで利用できます。Observableはプッシュ型であり、購読者にデータをプッシュ配信します。
一方、Subjectは、ObservableとObserverの両方の特性を持つ特殊な型です。値を発行するだけでなく、購読者からの値も受け取ることができます。Subjectは双方向型であり、データの流れを双方向に制御できます。
以下、ObservableとSubjectの主な違いをまとめます。
項目 | Observable | Subject |
---|---|---|
データの流れ | プッシュ型 | 双方向型 |
値の発行 | 可能 | 可能 |
値の購読 | 可能 | 可能 |
値の送信 | 購読者にプッシュ配信 | 購読者にプッシュ配信または購読者から受け取り発行 |
作成方法 | Observable.create() , from() , of() など | new Subject() |
具体的なユースケースとしては、以下のようなものが挙げられます。
- Observable: ネットワークリクエストのレスポンス、フォーム入力イベント、タイマーイベントなど、一方方向のデータストリームを扱う場合
- Subject: ログイン/ログアウト処理、チャットアプリケーション、双方向のデータ通信など、双方向のデータ制御が必要な場合
ObservableとSubjectは、どちらもRxJSにおける重要な概念ですが、それぞれ異なる性質と役割を持っています。それぞれの特性を理解し、適切な場面で使用することが重要です。
RxJSにおけるObservableとSubjectのサンプルコード
Observable
import { Observable, of } from 'rxjs';
import { subscribe } from 'rxjs/operators';
const observable = of(1, 2, 3);
observable.pipe(
subscribe(value => console.log('Observable value:', value))
)
このコードでは、of
関数を使って値 1, 2, 3
を発行するObservableを作成します。そして、subscribe
オペレーターを使ってObservableを購読し、発行された値をコンソールに出力します。
Subject
import { Subject } from 'rxjs';
const subject = new Subject();
subject.next(0);
subject.subscribe(value => console.log('Subject value:', value));
subject.next(1);
subject.next(2);
このコードでは、new Subject()
を使ってSubjectを作成します。そして、next
メソッドを使ってSubjectに値 0, 1, 2
を発行します。また、subscribe
オペレーターを使ってSubjectを購読し、発行された値をコンソールに出力します。
上記コードを実行すると、以下の出力が得られます。
Observable value: 1
Observable value: 2
Observable value: 3
Subject value: 0
Subject value: 1
Subject value: 2
Observableは、値を発行した後に購読しても、発行された過去の値は取得できません。一方、Subjectは、購読後でも発行されたすべての値を取得することができます。
以下のサンプルコードでは、ObservableとSubjectのより具体的なユースケースを紹介します。
ネットワークリクエストのレスポンスを扱う
import { Observable, fromEvent } from 'rxjs';
import { map } from 'rxjs/operators';
const fetchButton = document.getElementById('fetch-button');
const observable = fromEvent(fetchButton, 'click').pipe(
map(() => fetch('https://jsonplaceholder.typicode.com/todos/1'))
);
observable.subscribe(response => {
response.json().then(data => console.log('Todo:', data));
});
このコードでは、ボタンクリックイベントをObservableに変換し、ボタンクリック時にAPIリクエストを送信します。そして、APIレスポンスを購読し、取得したTodoデータをコンソールに出力します。
フォーム入力イベントを扱う
import { Observable, fromEvent } from 'rxjs';
import { debounceTime, map } from 'rxjs/operators';
const input = document.getElementById('search-input');
const observable = fromEvent(input, 'input').pipe(
debounceTime(300),
map(event => event.target.value)
);
observable.subscribe(query => console.log('Search query:', query));
このコードでは、入力フィールドの入力イベントをObservableに変換し、入力値の変化を300ms後に発行します。そして、入力値を購読し、コンソールに出力します。
チャットアプリケーションを構築する
import { Subject } from 'rxjs';
const chatSubject = new Subject();
const chatInput = document.getElementById('chat-input');
const chatList = document.getElementById('chat-list');
chatInput.addEventListener('input', (event) => {
const message = event.target.value;
chatSubject.next(message);
event.target.value = '';
});
chatSubject.subscribe(message => {
const listItem = document.createElement('li');
listItem.textContent = message;
chatList.appendChild(listItem);
});
このコードでは、Subjectを使ってチャットアプリケーションを構築します。入力フィールドに入力されたメッセージをSubjectに発行し、チャットリストに表示します。
ObservableとSubjectは、RxJSにおける強力なツールです。それぞれの特性を理解し、適切な場面で使用することで、より柔軟で効率的なアプリケーション開発が可能になります。
RxJSにおけるObservableとSubjectのその他の使い分け
既存のデータストリームを処理する場合、Observableが適しています。例えば、APIレスポンス、イベントストリーム、ファイル読み込みなど、外部ソースから提供されるデータストリームを処理したい場合に有効です。
例:
import { Observable, fromEvent } from 'rxjs';
import { map } from 'rxjs/operators';
const button = document.getElementById('my-button');
const observable = fromEvent(button, 'click').pipe(
map(event => event.target.textContent)
);
observable.subscribe(text => console.log('Button clicked:', text));
双方向のデータ通信を行う場合、Subjectが適しています。例えば、フォーム入力、チャットアプリケーション、リアルタイムデータ更新など、双方向でデータの送受信が必要な場合に有効です。
import { Subject } from 'rxjs';
const subject = new Subject();
subject.subscribe(value => console.log('Received value:', value));
subject.next('Hello!');
subject.next('World!');
値を共有する
複数のコンポーネント間で値を共有する場合、Subjectが適しています。例えば、複数のコンポーネントで同じデータを参照する必要がある場合や、コンポーネント間でイベントを発行・購読する必要がある場合に有効です。
import { Subject } from 'rxjs';
const counterSubject = new Subject();
const counterComponent = {
template: `
<button (click)="increment()">Increment</button>
<span>Count: {{ count }}</span>
`,
data() {
return {
count: 0,
};
},
methods: {
increment() {
this.count++;
counterSubject.next(this.count);
},
},
};
const logComponent = {
template: `
<span>Current count: {{ count }}</span>
`,
data() {
return {
count: 0,
};
},
mounted() {
counterSubject.subscribe(count => (this.count = count));
},
};
値をバッファリングする場合、ReplaySubjectが適しています。例えば、遅延が発生する可能性のあるデータストリームを処理する場合や、購読後に発行された過去の値を取得したい場合に有効です。
import { ReplaySubject } from 'rxjs';
const replaySubject = new ReplaySubject(2);
replaySubject.next(1);
replaySubject.next(2);
replaySubject.next(3);
replaySubject.subscribe(value => console.log('Received value:', value));
replaySubject.next(4);
最後の値のみを発行する場合、AsyncSubjectが適しています。例えば、データストリームが完了したときに最後の値を取得したい場合に有効です。
import { AsyncSubject } from 'rxjs';
const asyncSubject = new AsyncSubject();
asyncSubject.next(1);
asyncSubject.next(2);
asyncSubject.next(3);
asyncSubject.subscribe(value => console.log('Received value:', value));
asyncSubject.complete();
ObservableとSubjectは、それぞれ異なる性質と役割を持つため、適切な場面で使用することが重要です。上記の例を参考に、それぞれの使い分けを理解し、より柔軟で効率的なアプリケーション開発を目指しましょう。
javascript angular rxjs