RxJSをJava8のStreamAPIと比較してみた
きっかけ
RxJSって何だと思ってググると必ず「関数型リアクティブプログラミング(FRP)を実現するライブラリ」と出てきて、じゃあFRPって何だと思ってググると、そこは修羅の道。
でもよくよく調べてみたらFRPなんてそんなに理解してなくてもRxJSって使えるじゃんということに気づきました。そう思えたキッカケが、一見するとなんだか似ていそうなJava8のStreamAPI。そこで今回はStreamAPIと比較しながらRxJSについて整理してみました。
良いから結論だけ知りたいという場合は、まとめをどうぞ。
RxJSとはなんなのか - StreamAPIなのか?編
RxJSとは、Rx(Reactive Extensions)をJavaScriptで使えるようにしよう、というライブラリです。
ではRxとは何なのかというと、ざっくり言うとストリームというデータの流れを表すモノを、関数型のコレクションライブラリで加工できる仕組みみたいな感じです。
もう少し正確な表現だとRx = Observable + LINQ + Scheduler
となります。知らないものを3つも並べられると少しイラッとしますね😌
簡単に意訳すると…
Observable
= ストリームのことLINQ
= ストリームを操作する(subcribeする)ための関数型コレクションライブラリみたいなものScheduler
= 実行するスレッドやタイミングを制御するもの
と、概念を説明するよりソースを見たほうが理解が早いだろうということで、RxJSとStreamAPIの比較ソースを用意しました。以下の仕様で実装したソースです。
- 全ユーザーリストを取得する
- 「2017/01/01以降に入会した人」という条件でフィルタリングする
- フィルタリングされたユーザーのリストを返す
- フィルタリングされたユーザーをキャッシュする
JavaScript
let users = this.fetchUsers(); // userの配列を取得する
let userStream = Ex.Observable.fromArray(users); // userリストをstreamにする
let campaignTargets =
userStream
.filter((e) => {e.getJoinDate().after('2017-01-01')}) // フィルタリングする
.map((e) => {this.cache(e)}); // cacheする
Java
List<User> users = fetchUsers(); // userリストを取得する
List<User> campaignTargets =
users.stream() // streamにする
.filter(e -> {e.getJoinDate().after(DateTime.of(2017, 01, 01))}) // フィルタリングする
.map(this::cache(e)) // cacheする
.collect(Collectors.toList());
なんというか、似てる。
FRPとかよくわからないけど、StreamAPIのつもりで使えば良さそうな気がしてきました。
RxJSとはなんなのか - コンテナかもしれない編
RxJSが表現するObservableとはストリームのことだと言いましたが、ストリームが何者かという話です。ただの配列とどう違うのかが分かりそうで分からない。そんなときに理解が捗ったのは「1種のオブジェクト(コンテナ)だろう」というざっくりとした考え方でした。
システム的には配列よりは器用なことができて、要素をラップするコンテナの仲間だなーと思ってみたらしっくりきました。
こんな表が 関数型プログラマのための Rx 入門(後編)に記載されていて参考になりました。
単数 | 複数 | |
---|---|---|
同期 | Object | Iterable |
非同期 | Promise | Observable |
まとめ
結局Java8のStreamAPIっぽいじゃん
まじめなまとめ
- RxJSはRxの概念をJavaScriptで実現するためのライブラリ
- RxJSはざっくりいうとストリームを実現するためのライブラリ
- RxとはFRPの一種
- Rx = Observable + LINQ + Scheduler
- Observableはストリーム
- LINQは関数型のコレクションライブラリ
- Schedulerは実行するスレッドやタイミングを制御する闇の力
- 結局Java8のStreamAPIみたいなものと思っていればとりあえず触れた
本気で理解したかったら
以下を参考にするといいです。