點燈坊

失くすものさえない今が強くなるチャンスよ

自行建立 RxJS 的 exhaustMapTo() Operator

Sam Xiao's Avatar 2020-07-17

RxJS 有提供 exhaustMap(),卻沒提供 exhaustMapTo(),但我們可以自行建立 exhaustMapTo()

Version

macOS Catalina 10.15.5
WebStorm 2020.1.2
Vue 2.6.11
RxJS 6.5.5

exhaustMap()

exhaustmapto000

按下 Show Message 後,使用 exhaustMap() 攤平 higher order observable。

<template>
  <div>
    <button v-stream:click="click$">Show Message</button>
    <div>{{ number$ }}</div>
  </div>
</template>

<script>
import { interval } from 'rxjs'
import { exhaustMap, take } from 'rxjs/operators'

let subscriptions = function() {
  let interval$ = interval(1000).pipe(
    take(4)
  )

  let number$ = this.click$.pipe(
    exhaustMap(_ => interval$)
  )

  return { number$ }
}

export default {
  name:'App',
  domStreams: [
    'click$'
  ],
  subscriptions
}
</script>

13 行

let interval$ = interval(1000).pipe(
  take(4)
)

let number$ = this.click$.pipe(
  exhaustMap(_ => interval$)
)

click$ 為 Observable,且 interval$ 亦為 Observable,為了讓 interval$ 能完整顯示,在 interval$ 尚未顯示完全時,會取消 click$ 所提供的 value,這只能使用 exhaustMap()

因為 exhaustMap() 只能傳入 function,因此只能將 interval$ 包成 function 傳入。

exhaustMapTo()

<template>
  <div>
    <button v-stream:click="click$">Show Message</button>
    <div>{{ number$ }}</div>
  </div>
</template>

<script>
import { interval } from 'rxjs'
import { exhaustMap, take } from 'rxjs/operators'

let exhaustMapTo = o$ => exhaustMap(_ => o$)

let subscriptions = function() {
  let interval$ = interval(1000).pipe(
    take(4)
  )

  let number$ = this.click$.pipe(
    exhaustMapTo(interval$)
  )

  return { number$ }
}

export default {
  name:'App',
  domStreams: [
    'click$'
  ],
  subscriptions
}
</script>

exhaustMap() 類似的 mergeMap()concatMap()switchMap(),都有提供 mapTo() 版本的 mergeMapTo()concatMapTo()switchMapTo(),但直到 RxJS 6 都沒有 exhaustMapTo(),官方也沒特別解釋,但我們可自行實作 exhaustMapTo()

12 行

let exhaustMapTo = o$ => exhaustMap(_ => o$)

exhaustMapTo() 為 higher order function,可接受傳入 Observable,底層還是呼叫 exhaustMap()

19 行

let number$ = this.click$.pipe(
  exhaustMapTo(interval$)
)

有了 exhaustMapTo() 後,就可直接用在 pipe() 內,只要傳入 Observable 即可,不用再傳入 function,可將 exhaustMapTo() 寫在自己的 helper 或 library 內供日後重複使用。

Conclusion

  • RxJS 並沒有提供 exhaustMapTo(),但可以自行以 higher order function 實作 exhaustMapTo()