1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[RxJS小ネタ] switchMapで受け取った値もそのまま返す

Posted at

switchMap1でObservableを切り替える前の値もまとめて受け取れるようにしたい、もしくはcombineLatestのようなオペレータで実行順序を制御したいと思ったことはないでしょうか。

例えば以下のようにリクエストAの結果がリクエストBのパラメータとして必要な場合を考えます。

type A = { prop: string };
function requestA(): Observable<A>;
function requestB(prop: string): Observable<B>;

この場合は単にrequestBの結果を取得したい場合はそのままswitchMapを使うといいです。

requestA().pipe(
  switchMap(a => requestB(a.prop))
)
.subscribe(b => /* bを使った何か */);

しかし、リクエストAの結果もキャッシュしてコンポーネントのテンプレートに渡したい場合などでは、switchMap内もしくはtapオペレータでインスタンス変数に代入する必要があります。

requestA().pipe(
  tap(a => (this.a = a)),
  switchMap(a => requestB(a.prop))
)
.subscribe(b => {
  /* this.aを使った何か */
  /* bを使った何か */
});

このようなシンプルな例だとこのままの実装で問題ないのですが、リクエストを受け取ったあとに必要な処理が膨れ上がってきたり、依存関係のあるリクエストの数が増えると読みづらいコードになってしまいます。

一方、combineLatestやforkJoinのようなオペレータは複数のリクエスト結果をタプルで受け取ることができますが、リクエストの呼び出し順を指定したい場合には使えません。

const a$ = requestA();
const b$ = requestB(a.prop); // aをどうやってa$から取り出す?
combineLatest([a$, b$]).subscribe(([a, b]) /* 型は[A, B]のタプル */ => {
  /* ... */
}

解決策

そこで紹介するのはswitchMapのようにObservableを切り替えつつ、入力元の値も含めて返す方法です。
以下のような実装をします。

requestA().pipe(
  switchMap(a => requestB(a.prop).pipe(
    map(b => [a, b] as const)
  )
).subscribe(([a, b]) => {
  /* ... */
});

元々switchMapにはquerySelectorという引数でコールバックを指定できていましたが、RxJSからはこのquerySelectorはdeprecatedになっているので、代わりに上記のようにswitchMap内のmapで変換する必要があります。
そしてswitchMap内のconst assertionで型をタプルにしています。const assertionがないとsubscribeのコールバック引数の型が(A | B)[]のようになってしまいます。

ちなみにタプルではなくshorthand propertyとオブジェクトの分割代入で次のようにも書けます。

requestA().pipe(
  switchMap(a => requestB(a.prop).pipe(
    map(b => ({a, b}))
  )
).subscribe(({a, b}) => {
  /* ... */
});
  1. この記事ではswitchMapを例に説明していますが、mergeMap(flatMap), concatMap, exhaustMapでも同じです。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?