ECMAScript 2015 的 Promise 自帶 then()
,讓我們能類似 Functor 的 map()
或 Monad 的 chain()
直接修改 Promise 內部資料,唯 then()
是 Method Chaining 而不是 Function Pipeline,因此 Ramda 提供 Function 版的 then()
。
Version
Ramda 0.27.1
Promise
let data = 1
let f = x => Promise.resolve(x)
f(1)
.then(x => x * 2)
.then(x => x + 1)
.catch(console.error) // ?
Promise 具有 Functor 特性,因此可將 then()
當 map()
用。
then()
import { pipe, andThen as then, otherwise } from 'ramda'
import { resolve } from 'wink-fp'
let data = 1
let f = x => resolve(x)
pipe(
f,
then(x => x * 2),
then(x => x + 1),
otherwise(console.error)
)(1) // ?
但可惜 .then()
為 Method Chaining 而無法 Function Pipeline。
Ramda 另外提供了 andThen()
,此為 then()
的 function 版本。
andThen()
(a → b) → (Promise e a) → (Promise e b)
a -> b
:projection function
Promise e a
:data 為 Promise
Promise e b
:回傳全新 Promise
Ramda 在 0.26.1 之前使用
then()
,後來改成andThen()
較冗長,個人習慣將andThen()
改成then() 使用
Promise Monad
import { pipe, andThen as then, otherwise } from 'ramda'
import { resolve } from 'wink-fp'
let data = 1
let f = x => resolve(x)
pipe(
f,
then(x => x * 2),
then(x => x + 1),
then(x => resolve(x)),
otherwise(console.error)
)(1) // ?
Promise 是 Moand,除了可把 then()
當 map()
使用外,也可當成 chain()
使用,儘管回傳 Promise,最後也會被 flatten()
掉成為只有一層 Promise。
Composition Law
import { pipe, andThen as then, otherwise } from 'ramda'
import { resolve } from 'wink-fp'
let data = 1
let f = x => resolve(x)
let g = pipe(
x => x * 2,
x => x + 1
)
pipe(
f,
then(g),
otherwise(console.error)
)(1) // ?
因為 Promise 為 Moand,而 Moand 又是 Functor,因此支援 composition law,可將所有 then()
的 callback 組合成 function 後,再一次傳給 then()
即可。
Conclusion
- Ramda 0.26.1 的
then()
在 0.27.0 改成andThen()
,但所有功能都一樣,目的是讓 Promise 也能pipe()
與compose()
,個人習慣將andThen()
alias 成then()
使用較精簡