Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

歌舞伎座tech発表資料 RxJSの中を追う

4,458 views

Published on

歌舞伎座techのRxJSの内部処理を追ったスライドです。Hot/Coldのお話とか。

Published in: Software

歌舞伎座tech発表資料 RxJSの中を追う

  1. 1. RxJSの中を追う 安福 一樹 (wilfrem, @WilfremLuminous)
  2. 2. 自己紹介 名前: 安福 一樹 HN: wilfremとか@WilfremLuminous 仕事 Webエンジニア。 主にサーバサイドの開発をしています。 最近新部署に異動しました。 趣味 最近は面白技術を色々試して遊んでいる
  3. 3. はじめに
  4. 4. 今日のタイトルについて RxのHot/Coldを入り口に Rxが中で何をやっているかを追いたいと思い ます。 主に細かなところについて。 Rxにはどうしてもハマる点あるのですが Rxが中で何をやっているかが分かれば ハマりどころを回避できると思います。
  5. 5. 対象プラットフォームについて RxJS中心のお話になっていますが Rx.NET/RxJavaの実装と見比べてみたところ 言語ごとの実装に大きな違いはなく Rx.NET/RxJavaでも使える話になります スケジューラーしか大きな違いが無かった オペレータ名が微妙に違うのも LINQ引きずってる.NETだけの話だし
  6. 6. 本編
  7. 7. まずはこの問題のコードを御覧ください “side effect”は何回表示されるか? var rx = require("rx"); var s = new rx.Subject(); var stream = s.tap(function(){console.log("side effect");}); stream.subscribeOnNext(function(){}); stream.subscribeOnNext(function(){}); s.onNext("foo"); ちょっと読みにくいので図にします
  8. 8. 図にしてみた side effectは何回表示されるでしょうか? subject tap(do) side effect message onNext nop nop
  9. 9. 答え 2回 subject tap(do) side effect message onNext nop nop side effect
  10. 10. なぜ二回なのか? よくある説明 「doはColdなObservableだ」 →とても表面的な説明と理解 説明が良くない 現象の正しい理解のために Rxの動作原理を追ってみる
  11. 11. Rxのおさらい
  12. 12. Rxの基本要素 Rxのストリームと3種のメッセージ onNext* (onCompleted|onError)? onNext onNext onNext onCompleted
  13. 13. ObservableとObserver onNext(msg: T) onCompleted() onError(error: any) Observer<T>Observable<T> subscribe(o: Observer<T>) 1. subscribeする 2. つながる 3. messageがpushされる
  14. 14. Observableとオペレータ map filter throttle Observable map オペレータ=Observableを返す関数 RxにはObservableのメンバに様々なオペレータがある Observable
  15. 15. オペレータのチェーン map filter throttleObservable Rxのオペレータは繋げられる メッセージはオペレータに”加工”されて伝達する(onCompleted/onErrorも同様) map filter throttleObservable Observer message onNext onNext onNext onNext message subscribe
  16. 16. ところで……
  17. 17. オペレータはObservableである オペレータを重ねられる subscribeできる →Observableである Observable map オペレータはObservableである Observable
  18. 18. オペレータはObserverでもある? Observableに繋げられる メッセージを受け取れる →Observerである Observable map オペレータはObserverでもある Observer message Observer?いた?
  19. 19. しかし、オペレータの利用で Observerを見かけることはない
  20. 20. Observerはどこにいるのか?
  21. 21. 改めて: ObservableとObserver onNext(msg: T) onCompleted() onError(error: any) Observer<T>Observable<T> subscribe(o: Observer<T>) 1. subscribeする 2. つながる 3. messageがpushされる
  22. 22. 当然ですが、オペレータ=Observable  何度も説明したとおり、オペレータ=Observable  つまり、後ろのObserverにsubscribeされる  もちろん、後ろがオペレーターなら オペレーターがオペレーターをsubscribeする  どうやって……? map filter throttleObservable Observer subscribe
  23. 23. オペレーターがオペレーターを Subscribeする方法とは?
  24. 24. 答え: オペレータはObserverを生成する Observerを「生成」する 1つ手前のObservableをsubscribeする subscribeはチェーンする map filter throttleObservable Observer subscribe throttleObserver
  25. 25. Subscribeが完了すると 最終的にObservableにチェーンが到達 結果的にSubscribeすると Observerのチェーンが生成される map filter throttleObservable Observer メッセージ メッセージ メッセージ
  26. 26. オペレータの内部実装 ObservableBase(的な物)がある  =AnnonimousObservable  パフォーマンス改善verだと まさにObservableBaseが存在する subscribeだけ差し替えられる 各オペレータはsubscribeの差し替えを実装 差し替え処理で手前をsubscribeしている
  27. 27. Rxの”Hot”とは? Hot = Observerのチェーンを作ること。 Observerのチェーンを作るから メッセージが流れる RxのHotとは subscribeしてチェーンを作成すること。
  28. 28. チェインの行き着く先について
  29. 29. チェインの行き着く先 一番先頭のObservableはどういう物か? 2種類のObservableが存在する map filter throttleObservable Observer ?
  30. 30. タイプ1: “非保持型” 特徴  subscribeしてきたObserverを保持しない  何回subscribeしても同じ結果となる →例えばチェーンを何度も生成 例  just, create、大抵のオペレータなど =”Cold Observable”、Coldな性質と呼ばれる
  31. 31. タイプ2: “保持型” 特徴  subscribeしてきたobservableをキャプチャする  必要になった時にメッセージを流す  流す対象をリストとして持ち、分配機能を持つ 例  publish, fromEvent, Subject = “Hot Observable”、Hotな性質と呼ばれる Hot/Coldが分かりにくいのは 用語間違っているからな気がしている
  32. 32. 話をだいぶ戻して side effectはなぜ2回表示されるか? subject tap(do) side effect message onNext nop nop もう分かりますよね。
  33. 33. こうなるから subject tap(do) side effect message onNext nop nop side effect tap observer tap observer
  34. 34. では? side effectを1回だけ表示させるには? subject tap(do) side effect message onNext nop nop
  35. 35. 答え subjectを挟む subject tap(do) side effect message onNext nop nop subject
  36. 36. Subjectの役割 役割  SubjectはObserverをリストとして持つ  Observerとしてメッセージを受け取る  Observableとしてメッセージを配信する Subjectを挟むと”保持型”になる =Cold→Hot変換の正体  publish, share, fromeventは 内部でSubject使っている
  37. 37. Cold→Hot変換のconnect()とは Cold→Hot変換すると出てくる ConnectableObservable 中にSubjectがいる。 ConnectableObservable = Subject ConnectableObservable#connect()とは 内部のsubjectにsubscribeさせること。
  38. 38. 改めて、Rxは中で何をやっているのか? 復習を兼ねて
  39. 39. Rxの構成要素 Rxは (乱暴めに言うと) 5つの要素で構成されている Observable Observer ObserverとObservable BaseObservableと オペレータ subjectoperator SubjectとHot onNext* (onCompleted | onError)? scheduler Scheduler おまけで解説します ストリーム
  40. 40. Observableとオペレーター Observableに Operatorを繋げて 次のObservableを得 られる Observable Observable operator Observable
  41. 41. Observableとオペレーターの関係 オペレータは 手前の参照を持つ 後ろの参照はしな い メッセージは まだ流れない この状態=Cold Observable operator 参照 参照せず
  42. 42. Operatorの仕組み オペレータはほぼ 処理が共通 =ObservableBase subscribeを差し替え られるのみ Operator extends ObservableBase<T> subscribe(o: Observer<T>) 差し替え可能 Rxのオペレータは多数存在するが 大半はここの差し替えの違いのみ
  43. 43. subscribe差し替えの例 filter 条件に一致した時 に 次にメッセージを 流すObserverを 作成する map メッセージを変換 して流す Observerを作成する
  44. 44. subscribeの連鎖 Subscribe連鎖 Subscribeで 後ろのObserverを知 る Observerのチェーン が作成される Observable operator subscribe Observer Observer 参照
  45. 45. ストリームの作動 連鎖が完了 →Observerのチェー ンが完成 これで「作動」し メッセージが流れ る →Hotになる Observable operator Observer Observerメッセージ
  46. 46. Cold “Observable”とHot “Observable” Cold “Observable” Observer非保持 オペレータなら subscribeごとに チェーンを生成 Hot “Observable” Observer保持 分配機能を持つ Subjectでできている
  47. 47. メッセージの伝搬 Observer onNext() onCompleted() onError() Observer onNext() onCompleted() onError() message message message
  48. 48. メッセージはSubscribeに到達する Observer onNext() onCompleted() onError() subscriber subscribeOnNext() subscribeOnCompleted() subscribeOnError() message message
  49. 49. ストリームの終了 disposeを呼ぶか ストリームが終了で チェーンは消滅Observable operator Observer Observer Observable operator Observer dispose()
  50. 50. 以上がRxの中身になります
  51. 51. おまけ: Schedulerについて 流れ的に入らなかった……
  52. 52. スケジューラーとは  実行する関数をイベントキューに積む機構  メッセージの送信タイミングを変えられる  スレッドも変えられる 関数 イベントキュー スレッド・イベントループ 関数 関数 キューに積む 実行
  53. 53. Schedulerの実装 Rxの実装方法は言語によって違いはない 例外がScheduler スレッドが使えるかどうか? イベントループはあるか?
  54. 54. Rx.NET/RxJavaのScheduler 出来ること  スレッド切り替え(新規スレッド・ワーカー)  スレッド同期  イベントキューへの積み込み  etc. 大体の物は用意されている
  55. 55. RxJSにおけるScheduler イベントループに積む/積まないのみ。  シングルスレッドですし…… Scheduler.defaultが使える 積む関数は適切に選ばれる  node.jsはsetImmediate→nextTick  ブラウザはsetImmediate→MessageChannnel→ postMessage→onReadyStateChanged→ setTimeout
  56. 56. スケジューラーの使いどころ 重たい処理 処理を一息つかせたい時 スレッド切り替え/同期したい時
  57. 57. observeOnとsubscribeOnの違い observeOn メッセージが来た時 メッセージ処理に イベントループや スレッド切り替えを 挟む subscribeOn subscribe時の チェーン生成時 チェーン生成の スレッドを変えられ る 何に使うんだろ?
  58. 58. 以上です ご清聴ありがとうございました

×