33
30

More than 5 years have passed since last update.

RxJS 6: オペレータをつくってみる

Last updated at Posted at 2018-07-02

RxJS 6公式サイトはベータ段階のようで、まだチュートリアル(Overview)の情報が「Introduction」しかありません。そこで、バージョン5の「Overview」を下じきに、バージョン6に対応させたうえ、コードや解説も改めて「RxJS 6入門」01-07を書きました。

中でも「RxJS 6入門 06: Observableをつくる関数とオペレータ」は、ほぼ書き直しでした。そこで本稿では、RxJS 6のオペレータの使い方をかいつまんでおさらいし、簡単なオペレータを自作してみます。オペレータの仕組みを理解するのに役立つでしょう。

ライブラリをCDNから読み込む

今回は手軽に試せるように、RxJSライブラリはCDNから読み込みます。GitHubの「Installation and Usage」の「CDN」にしたがって、<script>要素につぎのようにsrc属性を定めてください。

<script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>

前にあったRxJS 5.5のCDNは消されたようです。RxJS 6公式サイトの「Installation Instructions」のページも「CDN」の情報がバージョン5.0から更新されていません。

クラスと関数およびオペレータの読み込みパス

バージョン6でまず気をつけなければならないのは、ライブラリの読み込みパスです。おもなクラスと関数は名前空間がrxjsにまとめられ、オペレータはrxjs.operatorsになりました(「Installation and Usage」参照)。

const {Observable, Subject, ReplaySubject, from, of, range} = rxjs;
const {map, filter, switchMap} = rxjs.operators;

npmでECMAScript 2015(ES6)CommonJSを使う場合は、それぞれリンク先のGitHubのページをご覧ください(なお「Import paths」参照)。

pipe()メソッドでオペレータを使う

RxJS 6では、オペレータはpipe()メソッドの引数に渡さなければなりません。このメソッドそのものは、バージョン5.5で備わったものです(「Operator pipe syntax」)。けれどこのときは、Observableのメソッドとしてオペレータを呼び出すバージョン5の書き方もできました。それがpipe()メソッド一択になったということです。

つぎのコードは、from()関数が配列からつくったObservableに、pipe()メソッドでmap()オペレータを適用しています。送られた値はオペレータが2乗して、コンソールに出力するという流れです。

const {from} = rxjs;
const {map} = rxjs.operators;
const observable = from([1, 2, 3, 4, 5])
.pipe(
    map((x) => x ** 2)
)
.subscribe(
    (x) => console.log(`value: ${x}`)
);
value: 1
value: 4
value: 9
value: 16
value: 25
  • from(): 配列や配列型(array-like)オブジェクト、Promise、反復可能(iterable)オブジェクト、あるいはObservableから新たなObservableをつくって返します。
  • map(): もとのObservableから送られた値に引数のプロジェクト関数を適用し、その戻り値が新たな値となるObservableにして返します。
  • **: べき乗演算子(ECMAScript 2016)。左オペランド(被演算子)を右オペランドで累乗します。
  • ``: テンプレート文字列(ECMAScript 2015)。組み込み式${}を扱うことができる文字列リテラルです。

オペレータの働きをする関数

オペレータが何をしているのか、簡単な関数をつくって確かめてみましょう。つぎの関数(square)は、送られた値を2乘するオペレータです。引数にObservableを受け取って、新たなObservableにして返します。その戻り値のオブジェクトに、オペレータの処理(2乗)をサブスクライブするのです。

const {Observable, from} = rxjs;
function square(input) {
    return Observable.create((observer) => {
        input.subscribe({
            next(value) {observer.next(value ** 2);},
            error(err) {observer.error(err);},
            complete() {observer.complete();}
        });
    });
}
const input = from([1, 2, 3, 4, 5]);
square(input)
.subscribe(
    (x) => console.log(`value: ${x}`)
);

もっとも、この関数はオペレータの働きを示しただけです。標準のオペレータのようにpipe()の引数には渡せません。

関数をpipe()メソッドに渡す

前掲の関数(square())は、引数にObservableを受け取って、新たなObservableにして返しました。pipe()メソッドがやっているのは、オペレータにObservableを渡すことです。そのため、引数はObservableが受け取れる関数を返さなければならないのです。

したがって、つぎのようにObservableを受け取って前掲関数が返される無名関数にすれば、pipe()メソッドの引数に与えられます。

// const input = 
from([1, 2, 3, 4, 5])  // ;
.pipe(
    (input) => square(input)
)
// square(input)
.subscribe(
    (x) => console.log(`value: ${x}`)
);

pipe()メソッドに渡せるオペレータを定める

つまり、前掲関数(square())は入れ子にして、つぎのように関数を戻り値にすれば標準のオペレータと同じ使い方ができるのです。

// function square(input) {
function square() {
    return (input) =>
    /* return */ Observable.create((observer) => {
        input.subscribe({
            next(value) {observer.next(value ** 2);},
            error(err) {observer.error(err);},
            complete() {observer.complete();}
        });
    });
}
from([1, 2, 3, 4, 5])
.pipe(
    // (input) => square(input)
    square()
)
.subscribe(
    (x) => console.log(`value: ${x}`)
);

オペレータをつくるというお題は、RxJSドキュメントの「Pipeable Operators」に「Build Your Own Operators Easily」として例が掲げられています。ご興味があればご覧ください。

RxJS 6入門

33
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
30