點燈坊

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

如何同時使用 RxJS 與 Ramda ?

Sam Xiao's Avatar 2020-06-10

RxJS 與 Ramda 同屬 Functional Library,RxJS 特色在於 Asynchronous 部分,而 Ramda 則在於 Synchronous,事實上 RxJS 與 Ramda 可搭配 Vue 一起使用。

Version

macOS Catalina 10.15.4
VS Code 1.44.3
Quokka 1.0.287
RxJS 7.0.0
Ramda 0.27.0
Vue 2.6.11

RxJS

import { interval } from 'rxjs'
import { map } from 'rxjs/operators'

interval(1000)
  .pipe(map(x => x * 2))
  .subscribe(x => console.log(x))

interval() 每秒建立 Observable,想透過 map() 將其乘以 2,最後 console.log() 印出。

ramda000

Ramda

import { interval } from 'rxjs'
import { map } from 'rxjs/operators'
import { multiply } from 'ramda'
import { log } from 'wink-fp'

interval(1000)
  .pipe(map(multiply(2)))
  .subscribe(log)

雖然 RxJS 是 asynchronous,但 operator 的 callback 則是 synchronous,因此這部分可使用 Ramda。

  • x => x * 2 改用 Ramda 的 multiply(2) 產生
  • x => console.log(x) 改用 Wink-fp 的 log() 產生

ramda001

Function Composition

import { interval } from 'rxjs'
import { map } from 'rxjs/operators'
import { multiply, compose } from 'ramda'
import { log } from 'wink-fp'

let calculate = compose(map, multiply)

interval(1000)
  .pipe(calculate(2))
  .subscribe(log)

RxJS 的 callback 常會看到類似 map(multiply(2)) 形式,這是典型的 f(g(x)),也就是 Function Composition,可使用 Ramda 的 compose() 加以組合。

ramda002

Vue-rx

<template>
  <div>
    <h1>{{ stream$ }}</h1>
  </div>
</template>

<script>
import { interval } from 'rxjs'
import { map } from 'rxjs/operators'
import { multiply, compose } from 'ramda'

let calculate = compose(map, multiply)

let subscriptions = _ => {
  let stream$ = interval(1000).pipe(
    calculate(2)
  )

  return { stream$ }
}

export default {
  name: 'app',
  subscriptions
}
</script>

14 行

let subscriptions = _ => {
  let stream$ = interval(1000).pipe(
    calculate(2)
  )

  return { stream$ }
}

subscriptionsdata 一樣,本質是 function,將所有 Observable 處理與宣告都在 subscriptions() 內。

15 行

let stream$ = interval(1000).pipe(
  calculate(2)
)

定義 stream$ Observable,由 RxJS 的 interval() 搭配 pipe() 產生。

12 行

let calculate = compose(map, multiply)

一樣使用 Ramda 的 compose() 組合 map()multiply()

ramda003

Conclusion

  • RxJS 與 Ramda 雖然分屬兩個不同的 library,但彼此可以相互搭配,使 RxJS 也能 享受 point-free 與 Function Composition

Reference

Milosz Piechocki, Better RxJS code with point-free style