RxJSをはじめる


RxJS?


reactivex.io


RxJS?

  • Observable ストリームによる非同期プログラミングのためのAPI
  • Rx(ReactiveX)というほぼ共通のAPIでいろんなプラットフォームへの実装がある
    • Rx.NET(オリジナル), RxJava, RxJS, ...
  • デザインパターンのObserverパターンがベース
  • AngularはRxJS使いまくってる

Observer デザインパターン

  • Observable
    • 非同期に値を出すやつ
  • Observer
    • その値を受け取ってなんかするやつ
  • イベントとイベントリスナーみたいなやつ
  • Observable ≒ JSのPromise,ScalaのFutureで値が何回も来るやつ

PromiseとObservable

// Promiseを返す
axios.get('/api/foo')
  .then(data => ...)
  .catch(err => ...);

// PromiseをObservableにできる
Rx.Observable.fromPromise(axios.get('/api/foo'))
  .subscribe(
    data => ...,
    err => ...
  );
// subscribeメソッドに成功、失敗のコールバックを渡す

// AngularのhttpクライアントはObservableを返す
http.get('/api/foo')
  .subscribe( 
    data => ...,
    err => ...
  );

Promise

  • thenに成功、catchにエラー時のコールバックを書く
promise
  .then(data => ...)
  .catch(err => ...);

// こういう書き方もできる
promise.then(data => ..., err => ...);

Observable

  • subscribeがコールバックを3つとる
    • onNext, onError, onCompleted
observable.subscribe(
  data => ..., // Promise.then
  err => ..., // Promise.catch
  () => ... // Promiseにはない
// Observableが途切れたときのonCompletedコールバック
);

  • onCompleted, onErrorは省略してもよい

Observableとイベント

document.addEventListener('click', ev => ...);

Rx.Observable.fromEvent(document, 'click')
  .subscribe(ev => ...);

RxJSの特徴

  • 非同期のイベント管理に強い
    • inputへの入力を500msスロットルしてAPIのこことあそこに投げた結果を待ち受けて成功だった場合だけ結果をくっつけて文字列にして返すObservable

RxJSの特徴

  • Observableに死ぬほど(120個くらい)メソッドが生えてる
  • Observableの亜種が10個くらいある
    • Subject, AsyncSubject, ...
  • 学習コストは高い
    • hot, coldの概念とか
  • その分メソッドチェーンがキマると気持ちいい
  • メソッドが死ぬほど生えてるということは型やIDEによる補完が無いと死ぬ
    • TypeScriptで再実装された

再実装?

        _人人人人人人人人_
        > まぎらわしい <
         ̄Y^Y^Y^Y^Y^Y^Y ̄

基本的なやつ

  • map, filter
Rx.Observable.from([1,2,3,4]) // 1,2,3,4
  .filter(x => x % 2 == 0) // 2, 4
  .map(x => x * 10) // 20, 40
  .subscribe(x => console.log(x))
// 20
// 40

ありがちなやつ

  • APIからユーザー情報を取得して、そのユーザーが担当になっている面接を取得する
http.get('/api/account')
  .map(data => data.json())
  .mergeMap(me => http.get(`/api/interviews/${me.id}`)
  .map(data => data.json())
  .subscribe(interviews => ...);

マーブルダイアグラム

RxのObservableストリームの図示によく使われる


marble testing

コードでマーブルダイアグラムを書いてテストするおしゃんな仕組み

const e1 = hot('----a--^--b-------c--|');
const e2 = hot(  '---d-^--e---------f-----|');
const expected =      '---(be)----c-f-----|';

expectObservable(e1.merge(e2)).toBe(expected);

rxjsをREPLっぽくさわる

  • ビルドされたRxJSをロードするhtmlを書いて、Chromeで開いてDeveloper Console
    • なぜか補間が割と効いてくれる
    • <head> の中に <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.0/Rx.js" type="text/javascript"></script>


Rxやるしかない

  • AngularはRxJSまみれ
  • RxJavaはAndroidとかでよく使われるらしい
  • Java9で標準APIに入るReactive StreamsはRx + back pressureみたいのらしい?

おわり