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.

マーブル図で怖くないRxJS

Rx初心者がいきなりRxJSのコードを見ると「RxJS意味がわからない、怖い」という印象を持ちがちです(実体験)。
そんなRxJSもマーブル図でゆるく理解すれば怖くありません。
初心者向けにマーブル図を紹介します。また実際にプロダクトで実装したRxJSの活用事例を紹介します。

  • Be the first to comment

マーブル図で怖くないRxJS

  1. 1. マーブル図で怖くないRxJS 管理画面アプリケーションでの活用 システム部 おくなも
  2. 2. © bitbank inc. 今日話すこと ● 前提 ● なぜ怖いのか? ○ パラダイムが違うから ○ どうちがうのか(ざっくり) ○ なにが嬉しいのか ● ゆるくマーブル図で理解してしまう ○ マーブル図の見方 ○ Operator, Indexの例 ● マーブル図で思考して実装する ○ 実際にプロダクトで使っているフロントエンド RxJS 2
  3. 3. 前提 JSとかTSしか知らない人に対する RxJS触り初めの取っ付きの悪さ についての話 3 https://www.quora.com/What-if-the-force-applied-is-less-than-static-fri ction-force
  4. 4. 4 @ocknamo ● 京都府出身 ● 2015年ごろから暗号通貨エンジョイ勢 ● 2018年6月に未経験からビットバンク入社 ● Nest.jsとAngularを使って管理画面を作ったりしています
  5. 5. © bitbank inc.  「RxJS? JSのライブラリか。JS って付いてるしMoment.jsみたいなもんや ろ」 5
  6. 6. © bitbank inc. 管理画面にもともとあったコード 6 getAll$ = this.actions$.pipe( ofType<RequestHttpGetUserInfos>(UserInfoActionTypes.RequestHttpGetUserInfos), exhaustMap((action) => this.apiClient.getUserInfos(action.payload.params).pipe( map((res) => new RequestHttpGetUserInfosSuccess({ models: res.items })), catchError((error) => from([new RequestHttpGetUserInfosError(error), new OpenNotification({ message: getErrorMessage(error) })])), ), ), );
  7. 7. 7
  8. 8. なぜ怖いのか? 8
  9. 9. © bitbank inc. パラダイムが違うから 手続き型 + OOP 9 サッカーのつもりできたら、いきなりカートに載せられた感じ https://www.flickr.com/photos/scoregasm/1384378780 リアクティブ https://pixabay.com/photos/karting-racing-car-car-sports-car-2979301/
  10. 10. © bitbank inc. どうちがうのか(ざっくり) ● 手続き型 + OOP 値を変数に代入して処理する ● リアクティブ 値(イベント)がストリームを流れてきてそれに対して色々処理を行うイメージ 10
  11. 11. © bitbank inc. なにが嬉しいのか ストリーム的な物事をストリーム的に考えられる! ● ストリーム的な物事 ○ 非同期のイベントが連続的に流れてくる処理 ■ APIのレスポンス ■ クリックイベント ■ 文字入力イベント ■ … 11
  12. 12. ゆるくマーブル図で理解してしまう 12
  13. 13. © bitbank inc. マーブル図の見方 13 RxJS Marble diagrams 1 2 3
  14. 14. © bitbank inc. マーブル図の見方 14 Event 1 2 3 RxJS Marble diagrams
  15. 15. © bitbank inc. マーブル図の見方 15 Next 1 2 3 Error Complete RxJS Marble diagrams
  16. 16. © bitbank inc. マーブル図の見方 16 RxJS Marble diagrams 1 2 3 Observable<T>
  17. 17. © bitbank inc. マーブル図の見方 17 矢印は時間の流れる方向 1 2 3 1 2 3 1 2 3
  18. 18. © bitbank inc. Operator, Indexの例 18 filter https://rxmarbles.com 条件に合致しないイベントをストリームから取り除く
  19. 19. © bitbank inc. Operator, Indexの例 19 forkJoin https://rxjs-dev.firebaseapp.com/a pi/index/function/forkJoin 複数のストリームをまとめて最後の値を配列で返すストリームをつくる
  20. 20. マーブル図で思考して実装する 20
  21. 21. リアクティブな検索フォーム 1. 入力イベントを受け取る 2. 3文字以上であるイベントだけフィルター する 3. 1000ミリ秒待って他のイベントが流れて こなかったらAPIを発火する 4. 値を受け取って表示する 1行で。 ● フォームに文字が3文字以上入力され、その 後1000ミリ秒フォームの内容が変更されな かったら検索を実行する 21
  22. 22. 1行で。 ● フォームに入力すると文字数が3文字以上で 入力されてから1000ミリ秒変更されなかった ら検索を実行する 22 h ho hog hoge hog hoge hoge 1000ms リアクティブな検索フォーム
  23. 23. 1行で。 ● フォームに入力すると文字数が3文字以上で 入力されてから1000ミリ秒変更されなかった ら検索を実行する 23 h ho hog hoge hog hoge hoge 1000ms リアクティブな検索フォーム filter(v => v.length > 2) debounceTime(1000)
  24. 24. リアクティブな検索フォーム 1行で。 ● フォームに入力すると文字数が3文字以上で 入力されてから1000ミリ秒変更されなかった ら検索を実行する 24 this.serchFormChange$ .pipe( filter(v => v.length > 2), debounceTime(1000), ) .subscribe((values) => this.store.dispatch( new RequestGetHogeById(values)), );
  25. 25. Csvダウンロード 1. 配列を受け取る 2. 空配列をフィルタ 3. 配列をマッピング 4. CSVダウンロードする 5. エラーハンドリング 6. ストアのリセット一行で ● 受け取ったデータ(モデルの配列)を整形して ブラウザからダウンロードし、失敗した場合は エラーメッセージをだして、成否に関わらずス トアをリセットする。 25
  26. 26. Csvダウンロード 一行で ● 受け取ったデータ(モデルの配列)を整形して ブラウザからダウンロードし、失敗した場合は エラーメッセージをだして、成否に関わらずス トアをリセットする。 2626 [ ] [models] [models] [mapped models] [mapped models] [mapped models]
  27. 27. Csvダウンロード 一行で ● 受け取ったデータ(モデルの配列)を整形して ブラウザからダウンロードし、失敗した場合は エラーメッセージをだして、成否に関わらずス トアをリセットする。 2727 [ ] [models] [models] [mapped models] [mapped models] [mapped models] filter(v => v.length !== 0) map(models => mapModels(models)) tap(data => downloadCsv(data)) catchError(e => openErrorMessage(e))
  28. 28. Csvダウンロード 一行で ● 受け取ったデータ(モデルの配列)を整形して ブラウザからダウンロードし、失敗した場合は エラーメッセージをだして、成否に関わらずス トアをリセットする。 2828 this.models$ .pipe( filter((v) => v.length !== 0), take(1), map((models) => mapModels(models)), tap((data) => { downloadCsv (data); }), catchError((e) => openErrorMessage(e), ) .subscribe((v) => { this.store.dispatch(new ResetModels ()); });
  29. 29. 連続的なAPIリクエストをフロ ントでハンドリングする 一行で ● 500件のAPIリクエストを一度に行うユース ケースがあるが負担の平準化のため 50件ず つ送ってレスポンスが返ってきてから次のリ クエストを送りたい 29 0. (配列をObservableに変換する) 1. イベントを50件ごとにまとめる 2. まとめたリクエストそれぞれは非同期で 処理する 3. 50件のリクエストは同期的に処理する
  30. 30. 連続的なAPIリクエストをフロ ントでハンドリングする 一行で ● 500件のAPIリクエストを一度に行うユース ケースがあるが負担の平準化のため 50件2 件ずつ送ってレスポンスが返ってきてから次 のリクエストを送りたい 30 1 selects = [1, 2, 3, 4, 5, 6 ] 2 3 4 5 6 [1,2] [3,4] [5,6] r1 [r1, r2] [r3, r4] [r5, r6] r2 ,・・・(省略) [r1, r2] [r1, r2] [r1, r2]
  31. 31. 連続的なAPIリクエストをフロ ントでハンドリングする 一行で ● 500件のAPIリクエストを一度に行うユース ケースがあるが負担の平準化のため 50件2 件ずつ送ってレスポンスが返ってきてから次 のリクエストを送りたい 31 1 2 3 4 5 6 [1,2] [3,4] [5,6] r1 [r1, r2] [r3, r4] [r5, r6] r2 ,・・・(省略) from([1, 2, 3, 4, 5, 6, ]) bufferCount(2) concatMap(...) forkJoin(...) [r1, r2] [r3, r4] [r5, r6] selects = [1, 2, 3, 4, 5, 6 ]
  32. 32. 連続的なAPIリクエストをフロ ントでハンドリングする 一行で ● 500件のAPIリクエストを一度に行うユース ケースがあるが負担の平準化のため 50件2 件ずつ送ってレスポンスが返ってきてから次 のリクエストを送りたい 32 const selects = ['1', '2', '3', '4', '5', '6']; from(selects) .pipe( bufferCount(2), concatMap((items) => { const requests$ = items.map((item) => // APIリクエスト // this.apiClient.postHoge(item); // デモ用のコード of(`response ${item}`).pipe(delay(1000)), ); return forkJoin(requests$); }), ) .subscribe((v) => console.log(v)); ※エラーハンドリングの実装は省略
  33. 33. © bitbank inc. Demo 33 https://stackblitz.com/edit/typescript-rx-playground-obvp3i?file=index.ts
  34. 34. © bitbank inc. WEB ● ReactiveX http://reactivex.io/documentation ○ マーブル図とドキュメント(英語)が充実してる ○ 知らないオペレータとか探すのには重宝する ○ JSに限ったドキュメントじゃない ● RxJS公式リファレンス https://rxjs-dev.firebaseapp.com/api ○ マーブル図とサンプルコードとドキュメント完備(英語) ○ ある程度理解してたら使いやすいがReactiveXのほうが入門向け 本 ● Beginner's Guide to RxJS: Functional Reactive Programming in JavaScript (En… https://www.amazon.co.jp/dp/B077R2RLGW ○ かんたん、はやい、安い、初学者向けKindle本(英語) ドキュメント 34
  35. 35. 35 ビットコインの技術で 世界中にあらゆる価値を流通させる
  36. 36. © bitbank inc. END 36

×