when()
若在 pipe()
中以 Function Pipeline 使用沒有問題,但若要搭配 Promise Chain 該如何使用呢 ?
Version
Ramda 0.27.1
when()
import { pipe, andThen as then, otherwise, when, equals, add } from 'ramda'
import { resolve } from 'wink-fp'
let addAsync = x => y => resolve(x + y)
pipe(
addAsync(1),
then(when(equals(3), add(1))),
then(add(2)),
otherwise(console.error)
)(2) // ?
第 3 行
let addAsync = x => y => resolve(x + y)
addSync()
只是 x + y
的 asynchronous 版本,以 Promise 回傳。
第 6 行
pipe(
addAsync(1),
then(when(equals(3), add(1))),
then(add(2)),
otherwise(console.error)
)(2) // ?
在 pipe()
組合過程中包含了 addAsync()
,由於回傳為 Promise,若要在之後使用 when()
呢 ?
由於 addAsync()
回傳 Promise,這使的之後的 function 也都要回傳 Promise,因此每個都要使用 then()
。
在 then()
之內都是 Promise 內部值,因此 when()
可安心取得,就當成 synchronous 思考即可。
when()
包在 then()
之後還是回傳 Promise,因此繼續使用 then()
。
Composition Law
import { pipe, andThen as then, otherwise, when, equals, add } from 'ramda'
import { resolve } from 'wink-fp'
let addAsync = x => y => resolve(x + y)
let addSync = pipe(
when(equals(3), add(1)),
add(2)
)
pipe(
addAsync(1),
then(addSync),
otherwise(console.error)
)(2) // ?
第 5 行
let addSync = pipe(
when(equals(3), add(1)),
add(2)
)
若你覺得每個 function 都要 then()
很醜,由於 Promise 是 Monad,而 Monad 又是 Functor,因此 Promise 支援 Composition Law,可將 synchronous 部分單獨抽成 addSync()
。
第 10 行
pipe(
addAsync(1),
then(addSync),
otherwise(console.error)
)(2) // ?
如此整個 Promise Chain 就只剩下一個 then()
而已。
Conclusion
- 若要在 Promise Chain 使用
when()
有兩種方式:一種是將when()
躲在then()
內;另一種是乾脆使用 Compositon Law 將 synchronous 部分抽出新 function,最後一次傳給then()