點燈坊

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

使用 pipeP() 組合 Sync Function 與 Async Function

Sam Xiao's Avatar 2020-08-06

pipeP() 在 Ramda 0.26.0 已經被列為 deprecatedpipeWith() 取代,若我們還想使用 pipeP(),可自行使用 pipeWith() 組合。

Version

macOS Catalina 10.15.6
VS Code 1.47.3
Quokka 1.0.312
Wink-fp 1.20.71

pipe()

import { pipe, andThen } from 'ramda'

let add = x => y => x + y
let addAsync = x => async y => x + y

let f = pipe(
  addAsync(2),
  andThen(add(3)),
  andThen(addAsync(4))
)

f(1) // ?

pipe() 也可同時組合 sync function 與 async function,若第一個 function 為 async function,則後續 function 無論是 sync function 或 async function 都必須加上 andThen()

pipeP000

pipeP()

import { pipeP, add } from 'ramda'
import { async2 } from 'wink-fp'

let addAsync = async2(add)

let f = pipeP(
  addAsync(2),
  add(3),
  addAsync(4)
)

f(1) // ?

也因為一堆 function 都要加上 andThen(),Ramda 提出了 pipeP(),專門應付 sync function 與 async function 的組合。

pipeP()
((a → Promise b), (b → Promise c), …, (y → Promise z)) → (a → Promise z)
若第一個 function 為 async function,可使用 pipeP() 組合後續 sync function 或 async function

pipeP001

pipeWith()

import { pipeWith, andThen, unapply, add } from 'ramda'
import { async2 } from 'wink-fp'

let addAsync = async2(add)

let pipeP = unapply(pipeWith(andThen))

let f = pipeP(
  addAsync(2),
  add(3),
  addAsync(4)
)

f(1) // ?

pipeP() 在實務上很好用,只可惜在 0.26.0 被列為 deprecated,因為被 pipeWith() 所取代。

pipeWith() 雖然更萬用,但必須將 function 以 array 傳入,與傳統 pipe() 習慣不同。

我們可將 pipeWith()andThen() 組合,最後以 unapply() 轉成 variadic function。

pipeP002

Wink-fp

import { add } from 'ramda'
import { pipeP, async2 } from 'wink-fp'

let addAsync = async2(add)

let f = pipeP(
  addAsync(2),
  add(3),
  addAsync(4)
)

f(1) // ?

Wink-fp 已經支援 pipeP() 可直接使用。

pipeP003

Conclusion

  • pipe() 雖然也能同時組合 sync function 與 async function,唯若第一個 function 為 async function,則後續無論是 sync function 或 async function 都必須包在 andThen()
  • pipeP() 能同時組合 sync function 與 async function,其第一個 function 為 async function,後續可為 sync function 或 async function,且不必再使用 andThen(),若要處理 Rejected Promise 則組合 otherwise()
  • 若既有 codebase 已經使用 Ramda 的 pipeP(),可改用 Wink-fp 的 pipeP() 繼續使用

Reference

Ramda, pipe()
Ramda, pipeP()
Ramda, pipeWith()
Ramda, andThen()
Ramda, unapply()
Ramda, add()