JS の Operators (5) - Observable の結合 (2)


この記事は bouzuya's RxJS Advent Calendar 2015 の 7 日目かつ RxJS Advent Calendar 2015 の 7 日目です。

はじめに

今日も昨日に続いて ReactiveX の Operators の Combining について RxJS の API ドキュメントやソースコードを見ていきます。

また RxJS 4.0.7 を対象にしています。

Observable の結合 (2)

Observable.concat / Observable.prototype.concat

Observable.concatObservable.prototype.concat とはほとんど同じものです。どちらも最初の ObservableonCompleted で concat した次の Observable に switch していくイメージです。

import { Observable } from 'rx';

Observable
  .concat(
    Observable.from([1, 2, 3]),
    Observable.from(['A', 'B'])
  )
  .subscribe(
    value => console.log(`onNext: ${value}`),
    error => console.log(`onError: ${error}`),
    () => console.log('onCompleted')
  );
// onNext: 1
// onNext: 2
// onNext: 3
// onNext: A
// onNext: B
// onCompleted

ちなみに Observable.prototype.concatAllObservable.prototype.merge(1) (maxConcurrent = 1) で、 Observable.prototype.concatMapmap(selector).concatAll() です。

Observable.prototype.join

Observable.prototype.joinArray.prototype.join とは違います。どちらかというと SQL で table を join するイメージで、ふたつの Observable を join して、すべての組み合わせを列挙します。

第二・第三引数で、それぞれの値をどれだけの期間利用するかを指定できます。Observable.never() とすれば値は延々と使われます。

import { Observable } from 'rx';

const left = Observable.from([1, 2]).map(value => `l:${value}`);
const right = Observable.from([3, 4]).map(value => `r:${value}`)

left
  .join(
    right,
    () => Observable.never(),
    () => Observable.never(),
    (x, y) => `${x},${y}`
  )
  .subscribe(
    value => console.log(`onNext: ${value}`),
    error => console.log(`onError: ${error}`),
    () => console.log('onCompleted')
  );
// onNext: l:1,r:3
// onNext: l:2,r:3
// onNext: l:1,r:4
// onNext: l:2,r:4
// onCompleted

leftrightinterval(100) で区切ったり、never()timer(0) などに変えると動きの変化が見れると思います。

ただ、ぼくにはこれを使いこなせる気がしません。

Observable.prototype.and / Observable.prototype.thenDo / Observable.when

Observable.when(observable1.and(observable2).thenDo(selector), ...)

といった形で使用します。

when
  condition then do
  condition then do

っぽい構文をつくりたいのでしょうか……。

実装を軽く読むと

  • Observable.when は複数の Plan を引数にとって、それぞれを activate していく。
  • Observable.prototype.andnew Pattern([this, right])
  • Observable.prototype.thenDonew Pattern([this]).thenDo(selector)
  • Pattern.prototype.thenDonew Plan(this, selector)

という感じ。

要するに observable を複数束ねた Pattern と、Patternselector を加えた Plan とを用意して、実行すると。

複数の Observable を細かい制御をしながら結合してひとつの Observable をつくりたいのでしょうが、正直なところ、この構文の何が嬉しいのか、ぼくにはまだ分かっていないです。

おわりに

今日は Observable を結合する Operator の続きを書きました。

ぼくの理解力だとよく分からないものが多くて困ります。この Advent Calendar が終わるころには分かるようになるのでしょうか。