Skip to content

Instantly share code, notes, and snippets.

@tetsuharuohzeki
Last active August 4, 2018 06:46
Show Gist options
  • Save tetsuharuohzeki/be133d505b1eb91b4c72 to your computer and use it in GitHub Desktop.
Save tetsuharuohzeki/be133d505b1eb91b4c72 to your computer and use it in GitHub Desktop.
RxJSのいろいろ雑感(2015年8月末編)

RxJSのいろいろ雑感(2015年8月末編)

  • 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.

http://reactivex.io/intro.html

  • 函数型言語方面の着想由来ではあるが、LINQ to Eventsであり、compositonal eventsの提供が肝
  • SchedulerやSubject(オブザーバーパターンにおけるSubjectと同じ)をうまく使えないと話にならない
    • 他の言語向けportはともかく、RxJSを日本語で紹介している記事の多くはこれらの話をしないので、ほとんど役に立たない
    • 他の言語向けportは、Rx.Schedulerによるスレッド抽象化が必須なのに対し、JSではイベントループ抽象化しなくてもそれなりに動くため、見落としている記事が多い
  • RxJavaとかRx.NETとかUniRxでググった方が、(英語・日本語の区別なく)よっぽどまともな情報が出てくる
    • Rx自体が言語に依存しない抽象概念化してるので, 言語にこだわらない方が良い.
    • JS固有事例と汎用事例を分けた方が良いけど.

向くこと

  • 統一的なイベントの取り扱い
  • イベントフローの可視化
  • データフローの可視化
  • 依存関係の明示
  • 時間軸をx軸としたイベント集合へのクエリ
  • イベントの合成
  • JavaScriptのイベントループの抽象化

向かないこと or たぶんこれでやるべきではないこと

  • 俺の知ってる関数型言語○○と同じ書き方でJavaScriptが書ける
  • もはや誰も実態を知らないんじゃないかと疑わしくなる程度にバズっている「Functional Reactive ProgrammingでGUIプログラミング」を信じて夢を追い続ける

どうしてもFRPしたい人へ

RxJSでFRPっぽいものを提供するフレームワークとか探せば出てくると思うんで、それで我慢してください

RxJSを実際に使う時の雑感

  • 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を作る必要が有る

ReactJS + RxJS

  • 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を使うとか、そういう用途なら良い

APIとか

  • コレクション操作系のメソッドが主なので、だいたいそこらへんを覚える
  • 最初から全部覚えない

はじめに眺めるもの

暇があるときに読むと良いけど、読まなくてもなんとかなるもの

概念について

  • 以下の組み合わせで何ができるのか知るべき

  • Hot/Coldは, 概念のみを気にするべき

    • 何がHotで何がColdとか覚えようとすると詰むので, 努力してはいけない
  • Observable

    • Operator
    • Hot/Cold
  • Observer(Subscriber)

  • Subject

  • Scheduler

最低限、これは覚えておいた方が良いoperator

PromiseとArrayの延長で考えるとうまくいく

  • map
  • flatMap
  • filter
  • merge
  • zip
  • combineLatest
  • withLatestFrom

名前もしくは効用のどちらか一方を覚えておいて、あとでググれば良いoperator

「ああ、あったね、そんなのも」程度で良い

  • create()
  • from()
  • do()
  • scan()
  • share()
  • debounce(), throttleFirst()
  • toArray(), toMap(), toSet()
  • window(), buffer()
  • just(), throw(), never()

その他のoperator

締めの一言

  • 過剰な期待や夢を見ずに粛々と使うのが良い
  • 夢を見るならAltJSで頑張りましょう
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment