RxJSのobservableをマスターする。Angularにおける使い方も説明。

この記事では、JavaScriptのライブラリであるRxJsとRxJSが提供するObservableタイプについてAngularにおける実装例も交えながら説明する。
RxJSは難しくよくわからないが使わないわけにはいかないライブラリというイメージが強いかもしれない。
しかし、データのストリームという概念が分かれば、それほど難しくないので安心してほしい。
ObservableパターンはJavaScriptの非同期処理を理解うえで、Promiseと並んで重要な概念。ぜひ、マスターしてほしい。
なお、Promiseについて勉強したい人はこちらの記事を参考にしてほしい。
Contents
RxJSとは?

RxJS(ReactiveX for JavaScript)はJavaScriptのライブラリ。
ReactiveXは「RxJava」や「Rx.NET」などJavaScript以外のプログラミング言語のバージョンも存在する。
RxJsはObservableを中核とするイベント駆動型の非同期処理を実現する。
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));