- Rx for JavaScriptについて、色々触った結論としてはこんな感じ
- あくまでも現時点の感想なんで、そのうち認識が変わるかも
- JavaScriptでRxを使う人ターゲットなんで、他の言語portにも効く話かはわからない
- FRPライブラリではない(と考えた方がいい)
- 世のRxJS紹介記事の多くはFunctional Reactive Programmingのためのライブラリであり関数型バリバリのように語っている事例があるが、信じ切って書くとロクなことにならないので、「雰囲気が似てる」程度に思う程度がちょうどいい
It is sometimes called “functional reactive programming” but this is a misnomer. ReactiveX may be functional, and it may be reactive, but “functional reactive programming” is a different animal. One main point of difference is that functional reactive programming operates on values that change continuously over time, while ReactiveX operates on discrete values that are emitted over time.
- 函数型言語方面の着想由来ではあるが、LINQ to Eventsであり、compositonal eventsの提供が肝
- SchedulerやSubject(オブザーバーパターンにおけるSubjectと同じ)をうまく使えないと話にならない
- 他の言語向けportはともかく、RxJSを日本語で紹介している記事の多くはこれらの話をしないので、ほとんど役に立たない
- 他の言語向けportは、Rx.Schedulerによるスレッド抽象化が必須なのに対し、JSではイベントループ抽象化しなくてもそれなりに動くため、見落としている記事が多い
- RxJavaとかRx.NETとかUniRxでググった方が、(英語・日本語の区別なく)よっぽどまともな情報が出てくる
- Rx自体が言語に依存しない抽象概念化してるので, 言語にこだわらない方が良い.
- JS固有事例と汎用事例を分けた方が良いけど.
- 統一的なイベントの取り扱い
- イベントフローの可視化
- データフローの可視化
- 依存関係の明示
- 時間軸をx軸としたイベント集合へのクエリ
- イベントの合成
- JavaScriptのイベントループの抽象化
- 俺の知ってる関数型言語○○と同じ書き方でJavaScriptが書ける
- もはや誰も実態を知らないんじゃないかと疑わしくなる程度にバズっている「Functional Reactive ProgrammingでGUIプログラミング」を信じて夢を追い続ける
RxJSでFRPっぽいものを提供するフレームワークとか探せば出てくると思うんで、それで我慢してください
- TypeScriptとかみたいにIDE + 静的型チェックがある環境で使った方がいい
- 無くても使えなくはない
- N個のイベントソースを1個にまとめてsubscribeするのが強い
- RxJSはN個のイベントソースを1個にまとめることができるが、N個が可変だったりするケースに弱く、古典的なObserver patternっぽく書く必要が有る(まあ古典的なオブザーバーパターンよりひどいことには成らないけど)
- 末端となるObservableをsubscribeした際に、祖先方向に再帰的にsubscribeを行うことでイベントソースを開通させるdesignなため、subscribe後に、動的にObservableを追加することができない
- 減らすのはdisposeすれば良いので割となんとかなる
- そのようなケースでは中継となるRx.Subjectを用意しておいて、そこに流し込むようにする必要が有る.
- Rx.Observable.window()のように、Rx.Observableが内包しているコレクション
T
がObservableを内包している場合、個別にsubscribeして処理する必要が有る - 典型が、Obserbableが内包するオブジェクトが、
Array<T: Observable>
とかMap<K, V: Observable>
であるようなケース。これらの内包するObservableを継続してsubscribeするのが非常に面倒臭いObservable<Array<Observable<T>>>
とかね。
- Rx.Subjectを使わない場合、コレクションの中身がmutateされたことを検知できるようにする必要が有る
- Rx.Subjectを使わない場合、コレクションの中身を継続してsubscribeできるようなoperatorを作る必要が有る
- Rx.Observable.window()のように、Rx.Observableが内包しているコレクション
- ReactJSは、N個のイベントストリームを1個にまとめてシリアライズしたオブジェクトを求める傾向が強い
- つまり、イベントソースの数が静的に決まるようなUIとの相性は非常に良い
- このケースでは、「FRPっぽく」綺麗に書ける
- イベントソースが動的に変わるUIの場合、例えば、複数の情報を登録するような、フォームの数が動的に変わるようなUIの場合、動的に数量の変化する子フォームの変化を受け取るのが面倒臭い
- 前段の、イベントソースが可変長になる場合.
- この場合、Rx.Subjectを使って素直に変更を中継・送出してやるのが良い
- 無理をしてObservableだけで書こうとすると失敗する
- 無理をしない
- 「副作用を起こさない」とか考えない方が良い
- 一般的な手続き型言語でのプログラミングの範囲で「副作用を減らす」ようにする
- LINQ to Eventsであることを意識する
- 副作用を起こさないことよりも、副作用によって変更された値に依存する後続の処理に対して、確実に影響を起こし、前提条件の不一致を減らすことを意識するべき
- Rx.Subjectを使うとかでうまくやれるケースが多い
- LINQ to Events以上のことを頑張ってやろうとする
- 純粋函数志向言語っぽく頑張って書こうとする
- 「RxJSはFRPライブラリです!」とかドヤ顔で言って夢追い人になる
- たとえ死人が出ても副作用を起こさないという無駄に強い意思を抱く
- 「Rx.Schedulerでとりあえず次のイベントループに投げる」みたいなのを無計画にやる
- 「他の処理が完了していないのを待つ」用途で使うと、場当たり的な使い方になって破滅するので、なるべくやらない方が良い
- 副作用を伴う処理を実行する時(配列操作とか)、他のタスクが入り込まないようにRx.Scheduler.immidiateを使うとか、そういう用途なら良い
- コレクション操作系のメソッドが主なので、だいたいそこらへんを覚える
- 最初から全部覚えない
-
以下の組み合わせで何ができるのか知るべき
-
Hot/Coldは, 概念のみを気にするべき
- 何がHotで何がColdとか覚えようとすると詰むので, 努力してはいけない
-
Observable
- Operator
- Hot/Cold
-
Observer(Subscriber)
-
Subject
-
Scheduler
PromiseとArrayの延長で考えるとうまくいく
- map
- flatMap
- filter
- merge
- zip
- combineLatest
- withLatestFrom
「ああ、あったね、そんなのも」程度で良い
- create()
- from()
- do()
- scan()
- share()
- debounce(), throttleFirst()
- toArray(), toMap(), toSet()
- window(), buffer()
- just(), throw(), never()
- あとで調べれば良い
- わからなくても上を覚えておけば泥臭く書ける
- チュートリアルとか読む時は
range()
を覚えておくと読みやすい - 「コレクション操作の延長」「時間軸操作」の二点さえ理解しておけば、その延長で「探せばありそう」なものが思いつく
- 無くても凹まない
- 能動的に探したい時は、下を眺めるのも良いです
- 過剰な期待や夢を見ずに粛々と使うのが良い
- 夢を見るならAltJSで頑張りましょう