Angularで使っているrxJsのOperatorを簡単にまとめてみた


現在使用しているrxJsのOperatorを簡潔にまとめていきます。

随時、加筆修正します。

現在、利用中のversionは以下です。

p.json
    "@angular/core": "^8.2.9"
    "rxjs": "^6.5.1"

forkJoin

概要

複数のObservableから値を受けとった後で処理を走らせたいときに使います。

詳細

  1. subscribeされる 
    OBSERVER -> FORK JOIN
  2. ObservableAとBから値が流れてくる
    A -> [0-a, 1-a, 2-a] -> FORK JOIN
    B -> [0-b, 1-b, 2-b] -> FORK JOIN
  3. AとBそれぞれがCompleteされて値がそろう
    FORKJOIN : [0-a, 1-a, 2-a], [0-b, 1-b, 2-b]
  4. そろった値がまとめてobserverに送られる
forkJoin.ts
forkJoin([
        this.requestService.getPersons(),
        this.requestService.getParams()
      ]).subscribe(result => {
        const personList: Array<Person> = result[0];
        const params: AppParams = result[1];
        this.setUp(personList, params);
      })

上記のようなコードを描くとsubscribeされた後で this.requestService.getPersons()this.requestService.getParams() からforkJoinが値を受け取り続け、どちらもcompleteされて初めて setUp のメソッドが呼び出されます。

flatMap

概要

あるObservableのレスポンスをもとに別のObservableで値を取得したい時に使います。
ネストをせずに済むので可読性を向上できます。

詳細

flatMap.ts
this.queryParams.pipe(flatMap(param => {
     this.serviceId = param.sid;
     this.appId = param.appId;
     return forkJoin([this.getLayout(this.serviceId), this.getText(this.serviceId, this.appId)]);
})).pipe(flatMap(res => {
     this.layout = res[0];
     this.text = res[1];
     return this.appId ? this.service.get(this.appId) : null
})).subscribe(val => {
     ...
})

上記を日本語の手順で説明すると

  1. Paramが届いたら flatMap(param => {
  2. layoutとtextを取得する return forkJoin(this.getLayout(this.serviceId), this.getText(this.serviceId, this.appId));
  3. layoutとtextが取得できたら flatMap(res => {
  4. サービスで情報を取りに行くthis.appId ? this.service.get(this.appId) : null

となります。

ちなみにsubscribe()のなかでsubscribe()を呼ぶのはrxJsのアンチパターンなので絶対にしないようにしましょう。

There's no "harm", but this is considered an antipattern in rxjs. And if the three calls are independent this is unnecessarily slow.

Is it good way to call subscribe inside subscribe? より引用

補足

forkJoinのような生成系operatorと違って、flatMapのように流れてきたものに手を加えるoperatorは

hosoku.ts
observable
 .pipe(operator(引数))
 .subscribe(x => ...

このようにpipeの中にoperatorを入れて使用します。