RxJSでJavaScriptのリアクティブプログラミングを理解する!Angularを使った実装例。
この記事では、JavaScriptのライブラリである「RxJS」について詳しく解説したい。
RxJS(ReactiveX for JavaScript)はJavaScriptでリアクティブプログラミングをおこなうためのライブラリであり、代表的なJSフレームワークのAngularでは標準で実装されている。
この記事では、RxJSの仕組みはもちろん、よく使うオペレータやAngularにおける実装例を説明したい。
RxJSとは?
RxJSはJavaScriptの拡張ライブラリ。
「ReactiveX for JavaScript」の略であり、ReactiveXには「RxJava」や「Rx.NET」などのバリエーションが存在する。
ReactiveXはイベント駆動型の非同期処理を可能とするためのライブラリであり、Observableというオブジェクトを中心として構成される。
Observableはデータの更新をストリームとして送信・受信するための仕組みである。
JavaScriptフレームワーク「Angular」では、デフォルトのフレームワークとなっているので、Angularの開発者であれば一度は実務で使用したことがあるだろう。
Observableのアーキテクチャコンセプトである「オブザーバーパターン」はJavaScriptの非同期処理を理解するうえで重要な概念である。
Observableの使い方
では、Observableの仕組みとその使い方を見ていこう。
Observableの仕組み
まずはObservableの仕組みを説明する。
以下はObservableのデータの流れをイメージした図だ。
Observableでは、データを発信する側はObserver、データを受信する側はSubscriberと呼ばれる。
Subscribe(購読)されたObservableは値に変更がある度に送信され、オペレーターにより処理されたあとに購読者に届けられる。
Observableの仕組みはコールバックやEventEmitterなどとも似ている。
データを発信する Observer
では、Observableを使った実装例を見ていこう。
まずはデータを発信する側の例をいくつか見ていこう。
以下の例では、3つのString「firts」「second」「third」を順にストリーミングしている。
public textObservable: Observable<string> = of('first', 'second', 'third');
データ型をanyにすれば文字列と数を交互に送ることもできる。
public anyObservable: Observable<any> = of('first', 2, 3 + 'rd');
intervalメソッドを使用すれば一定の間隔でデータを送ることもできる。
public intervalObservable = interval(1000).pipe(take(4));
データを受信する Subscriber
次にデータを受信する例の見てみよう。
this.observerService.textObservable.subscribe(next => {
console.log(next);
})
Observableオブジェクトの次にsubscribeメソッドを使用してデータを購読する。
データを購読した場合はそれをSubscriptionオブジェクトに代入する。コンポーネントが消失する際には購読しているSubscriotionをunsubscribe(購読解除)するようにしよう。
一連の流れをコードにすると以下のようになる。
unsubscriptionメソッドを呼び出し購読を解除する。
private _textObservableSubscription: Subscription;
constructor() {}
ngOnInit() {
this._textObservableSubscription = this.anyObservable.subscribe(next => {
console.log(next);
})
}
ngOnDestroy() {
this._textObservableSubscription.unsubscribe();
}
オペレーター
次にデータを加工するために使用するオペレーターの中でよく使われるものを知っておこう。
ObservableをPromiseに変換する(toPromise)
Observableオブジェクトは簡単にPromiseに変換することが出来る。
Observableの最後にtoPromise()を追加しよう。
const promise = of(152, 12, 35).toPromise();
promise.then(number => console.log(number));
上のコードを実行するとObservableの最後の値である「35」が出力されるだろう。
map
まずは一番使われることが多いmapから見ていこう。
次の例は数字を文字列として加工して出力するパターン。
interval(1000).pipe(take(10)).pipe(map(number =>
'count ' + (number + 1)
)).subscribe(count => {
console.log(count);
});
以下の例はオブジェクトを使用したパターンだ。よく使われるので理解しておこう。
of({firstName : 'Nicholas', lastName: 'Barker'},
{firstName : 'Anthony', lastName: 'Mason'},
{firstName : 'Raphael', lastName: 'Gibson'},
).pipe(map(p => p.firstName + ' ' + p.lastName))
.subscribe(fullName => console.log(fullName));
filter
次にこれまたよく使われるfilterメソッドの例も見てみよう。
of(152, 12, 35, 4578, 3).pipe(filter(num => num > 50)).subscribe(num => console.log(num));