JavaScriptの最強ライブラリ「RxJS」!observableの使い方をマスターする。

JavaScriptの最強ライブラリ「RxJS」!observableの使い方をマスターする。

この記事では、JavaScriptのライブラリであるRxJSについてAngularにおける実装例も交えながら説明する。

Observableはデータの更新をストリームとして送信・受信するための仕組み。Angularの開発者であれば一度は実務で使用したことがあるだろう。

Observableのアーキテクチャコンセプトである「オブザーバーパターン」はJavaScriptの非同期処理を理解するうえでPromiseなどと並んで重要な概念だ。ぜひ、マスターしておいてほしい。

RxJSとは?

まずはRxJSについてもう一度説明しておきたい。

RxJS(ReactiveX for JavaScript)はJavaScriptの拡張ライブラリ

Observableを中核とするイベント駆動型の非同期処理を可能とする。
ReactiveXは「RxJava」や「Rx.NET」などJavaScript以外のプログラミング言語のバージョンも存在する。

JavaScriptフレームワーク「Angular」では、実装の一部としてデフォルトで使用できる。

Observableの使い方

では、Observableの仕組みとその使い方を見ていこう。

Observableの仕組み

まずはObservableの仕組みを説明する。

以下はObservableのデータの流れをイメージした図だ。

Observableでは、データを発信する側はObserver、データを受信する側はSubscriberと呼ばれる。

Subscribe(購読)されたObservableは値に変更がある度に送信され、オペレーターにより処理されたあとに購読者に届けられる。

ObserverとSubscriberは異なるコンポーネント内に存在する場合が多い。

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に変換する

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));