HTML5テクニカルノート
RxJS入門 06: オペレータ
- ID: FN1804001
- Technique: HTML5 / JavaScript
- Library: RxJS 5.5.8
RxJSの基礎となるのはObservable
です。オペレータはObservable
を操作するのにとても役立ちます。複雑な非同期の処理を、わかりやすいコードで組み立てられるのです。公式「Manual」の「Operators」を下じきに、サンプルコードや解説は改めました。
01 オペレータとは
オペレータはObservable
オブジェクトのメソッドです。map()
やfilter()
あるいはmerge()
などが備わっています。オペレータを呼び出しても参照したインスタンスは変えません。Subscription
の定めを受け継いだ新たなObservable
が返されるのです。オペレータは、もとのObservable
はそのままに、新たなObservable
をつくる純粋な関数といえます。
オペレータは、基本的にひとつのObservable
を入力として受け取り、もうひとつの新たなObservable
をつくって返す関数です。出力Observable
をサブスクライブすると、入力Observable
もサブスクライブされます。つぎのコードで定めたカスタムオペレータ関数は、入力Observable
から受け取る値をそれぞれ2乗します。出力オブジェクトに対してObservable.subscribe()
メソッドを呼び出したとき、入力Observable
もサブスクライブされることにご注目ください(後述のとおりObservable.subscribe()
は静的オペレータです)。 これを「オペレータサブスクリプションチェーン」と呼びます。
function square(input) { const output = Rx.Observable.create((observer) => { input.subscribe({ next(value) {observer.next(value ** 2);}, error(err) {observer.error(err);}, complete() {observer.complete();} }); }); return output; } const input = Rx.Observable.from([1, 2, 3, 4]); const output = square(input); output.subscribe((x) => console.log(x)); /* コンソール出力 1 4 9 16 */
02 インスタンスオペレータと静的オペレータ
オペレータを参照するとき、多くの場合はObservable
インスタンスのメソッドを考えます。たとえば、前掲コードのカスタムオペレータ関数(square())が、RxJSのインスタンスオペレータに組み込まれていたとしたら、以下のような実装になるでしょう。
インスタンスオペレータは、this
参照を入力Observable
として扱う関数です。ですから、オペレータの引数に入力Observable
は渡しません。参照するオブジェクトを入力とみなすのがインスタンスオペレータです。
Rx.Observable.prototype.square = function() { return Rx.Observable.create((observer) => { this.subscribe({ next(value) {observer.next(value ** 2);}, error(err) {observer.error(err);}, complete() {observer.complete();} }); }); } const observable = Rx.Observable.from([1, 2, 3, 4]).square(); observable.subscribe((x) => console.log(x)); /* コンソール出力 1 4 9 16 */
インスタンスオペレータのほかに、Observable
クラスに直接定められた関数である静的オペレータがあります。静的オペレータはthis
参照をもちません。引数にもとづいて、新たなObservable
を返します。Observable
インスタンスを新しくつくりたいときに用いられることが多いでしょう。
よく使われる静的オペレータは、生成オペレータです。入力Observable
から出力Observable
に変換するのではなく、引数に数値のようなObservable
でない値を受け取って、新しくObservable
をつくります。静的オペレータの典型として挙げられるのはinterval()
です。引数はObservable
でなく数値で、新しくObservable
をつくって出力として返します。
const observable = Rx.Observable.interval(1000); const subscription = observable.subscribe((x) => console.log(x)); setTimeout(() => subscription.unsubscribe() , 3000); /* コンソール出力 0 1 */
静的生成オペレータのもうひとつの例としては、すでにこれまでもたびたび使ってきたObservable.create()
があります。生成オペレータにどのようなものがあるかは、「Creation Operators」をご覧ください。
インスタンスをただつくるだけではない静的オペレータもあります。結合オペレータには、Observable.merge()
やObservable.combineLatest()
あるいはObservable.concat()
など静的なものがあります(「Combination Operators」参照)。これらは、複数の入力Observable
を引数に受け取るために、静的オペレータとされたのです。
Observable.merge()
メソッドは、引数のふたつの入力Observable
がひとつにまとめられた出力Observable
をつくって返します。つぎのコードでは、observable2から送られる値のふたつおきに、observable1の値が送り出されています。なお、take()
メソッドはObservable
から送られる値の数を引数値に止めます。
const observable1 = Rx.Observable.interval(1000).take(3); const observable2 = Rx.Observable.interval(400).take(6); const merged = Rx.Observable.merge(observable1, observable2); merged.subscribe((x) => console.log(x)); /* コンソール出力 0 1 0 // observable1 2 3 1 // observable1 4 5 2 // observable1 */
03 マーブルダイヤグラム
オペレータの働きを、文章だけで説明しようとするとかぎりがあります。オペレータの多くは時間に関わり、sample()
やthrottle()
あるいはdebounce()
など異なったやり方で値を送ります。それらは、図で説明するとわかりやすくなることが少なくありません。マーブルダイヤグラム(Marble Diagram)は、オペレータの働きを図で示したものです。その中には、入力Observable
やオペレータとその引数、さらに出力Observable
が含まれます。
つぎ図001が、マーブルダイヤグラムの例です。時間は左から右に流れ、マーブルで示された値がObservable
の実行によりどのように送られるのかを表しています。RxJS公式ドキュメントでは、マーブルダイヤグラムでオペレータの仕組みを説明しています。
図001■マーブルダイアログとその説明
04 オペレータの選択と分類
04-01 オペレータを選ぶ
RxJS公式サイトの「Choose an operator」では、リスト(英語)から求める項目を選んでゆくと適切なオペレータが示されます。
04-02 オペレータの分類
RxJSには、さまざまな目的のオペレータがあります。それらを分類したのが以下のリストです。分類項目はRxJS公式「Manual」の「Categories of operators」にリンクされており、それぞれの分類のオペレータが一覧でみられます。
- 生成オペレータ(Creation Operators)
- 変換オペレータ(Transformation Operators)
- フィルタリングオペレータ(Filtering Operators)
- 結合オペレータ(Combination Operators)
- マルチキャストオペレータ(Multicasting Operators)
- エラー処理オペレータ(Error Handling Operators)
- ユーティリティーオペレータ(Utility Operators)
- 条件・論理オペレータ(Conditional and Boolean Operators)
- 数学・集計オペレータ(Mathematical and Aggregate Operators)
RxJS入門
- RxJS入門 01: RxJSを使ってみる
- RxJS入門 02: Observable
- RxJS入門 03: Observer
- RxJS入門 04: Subscription
- RxJS入門 05: Subject
- RxJS入門 07: Scheduler
作成者: 野中文雄
作成日: 2018年4月2日
Copyright © 2001-2018 Fumio Nonaka. All rights reserved.