Help us understand the problem. What is going on with this article?

これだけ知ってれば大丈夫(かもしれない)RxJS5の厳選オペレータ

More than 3 years have passed since last update.

RxJS5のオペレータはだいぶ削減されたようですが、それでも100近くあります。
なのでRx歴3日の私がこれだけ知ってれば大丈夫かも?と思ったオペレータを(三日坊主を避けるために)つらつら並べます。理解が相当怪しいと思うので、突っ込み大歓迎です、むしろお願いします。

Reactive Programmingの荒い説明

例えば、ボタンが押されたら、入力した文字をWebAPIを叩いて検索して、結果を表示する、という処理を考えます。
すべてが同期的に行えるとしたら、以下のようになります。

function main(){
  if(button.click){
    let inputText = inputTextBox.text;
    let result = query(iniputText);
    outputTextBox.text = result;
  }
}

このうち、参照された変数が変更された場合(この場合だと、button.click、inputTextBox.text)、自動的にロジックの再計算を走らせたらどうでしょう?というのが基本的な考え方です。

これはつまり、変数に変更に対して反応するコードです。Reactive ProgrammingのReactiveとは、これを指します。

RxJS

JavaScriptはReactive Programming Languageではありませんので、この考え方をJavaScript界に具象化する必要があります。そのためのライブラリがRxJSになります。

何かに対して何かを行う、をつなげて、そこにメッセージを流し込む、というモデルです。

Observable

何に対して反応するか、その「何」にあたるのがObservableになります。

Operator

何をおこなうのか、その「何」に当たるのがOperatorです。

subscribe

Operatorの端点です。これが呼ばれないとなにも起きません。

厳選オペレータ

いきなりですが構造化プログラミングの基本です。
GOTO地獄から脱出するために必要なパーツは三つです。

  • 順次
  • 反復
  • 分岐

これをRxJSにおいてどう実現するか、そして、そのオペレータが基本的なOperatorであるとみなして並べます。

順次

流れてきたメッセージに対して処理を行います。

map

流れてきたメッセージに対して、変更を加えて、次に渡します。

do

メッセージが流れてきた、をトリガにして、処理を実行します。
主に副作用を担当します。

switchMap,concatMap,flatMap

switchMapは、流れてきたメッセージをObservableに変換する関数を受け取り、それに置き換えます。
concatMapは直列に、flatMapは並列に繋ぎます。
順次実行の文脈では、主な使い道としては非同期処理です。

text$
  .switchMap((t)=>query(t))
  .subscribe((t)=>console.log(t));

switchMapはPromiseを受け取ると、resolveされたらその値が流れるObservableに変換してくれます。
よって、もしquery()がPromiseを返す非同期処理ならば、

textにデータが流れて来たら、queryを実行、そして結果をコンソールに出力して、終了する。

という流れになります。

反復

そもそもObservableという概念が、反復を内包しています。よって、配列等、反復対象になるデータをObservableに変換する処理があればOK、ということになります。

concatMap

流れてきたメッセージをメッセージの流れに変換して、それを直列につなぎます。

array$
  .concatMap((ts)=>Rx.Observable.from(ts))
  .subsribe((t)=>console.log(t));

switchMap

また出てきましたが、例えば配列の終了通知が必要な場合は、こちらになります。

flatMap

こちらは並列なので、反復内容に非同期処理が混ざって、各々を止めたくない場合に使用します。

array$
  .switchMap((ts)=>Rx.Observable.of(ts))
  .flatMap(t=>query(t))
  .subsribe((t)=>console.log(t));

分岐

メッセージの分配と、その条件が必要になります。

share

流れてくるメッセージを分配します。注意したいのは、RxJSでは、以下は分配になりません。

let source$ = text$.do((v)=>doIt(v));
source$.subsribe((v)=>console.log(v));
source$.subsribe((v)=>console.log(v));

意図に反して、textにメッセージが流れるたび、doItが二回呼ばれます。
この挙動を理解するためにはHotとColdの概念を理解する必要があります。
また、参照透過なOperatorのみの場合上でもうまくいく等、無意味に複雑です。
最初のうちは、分配したい場合はshare、でよいと思います。

filter

条件を満たした場合、値を通過します。
分配した後、各々でfilterすれば、条件分岐は達成できます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした