con()
若在 pipe()
中以 Function Pipeline 使用沒有問題,但若要搭配 Promise Chain 該如何使用呢 ?
Version
Ramda 0.27.1
cond()
import { pipe, andThen as then, otherwise, cond, equals, T, add } from 'ramda'
import { resolve } from 'wink-fp'
let addAsync = x => y => resolve(x + y)
pipe(
addAsync(1),
then(cond([
[equals(2), add(1)],
[equals(3), add(2)],
[T, add(3)]
])),
otherwise(console.error)
)(1) // ?
第 4 行
let addAsync = x => y => resolve(x + y)
addSync()
只是 x + y
的 asynchronous 版本,以 Promise 回傳。
第 6 行
pipe(
addAsync(1),
then(cond([
[equals(2), add(1)],
[equals(3), add(2)],
[T, add(3)]
])),
otherwise(console.error)
)(1) // ?
在 pipe()
組合過程中包含了 addAsync()
,由於回傳為 Promise,若要在之後使用 cond()
該如何使用呢 ?
由於 addAsync()
回傳 Promise,這使的之後的 function 也都要回傳 Promise,因此每個都要使用 then()
跑不掉。
在 then()
之內都是 Promise 內部值,因此 cond()
可安心取得,就當成 synchronous 思考即可。
Extract Function
import { pipe, andThen as then, otherwise, cond, equals, T, add } from 'ramda'
import { resolve } from 'wink-fp'
let addAsync = x => y => resolve(x + y)
let calculate = cond([
[equals(2), add(1)],
[equals(3), add(2)],
[T, add(3)]
])
pipe(
addAsync(1),
then(calculate),
otherwise(console.error)
)(1) // ?
第 6 行
let calculate = cond([
[equals(2), add(1)],
[equals(3), add(2)],
[T, add(3)]
])
若你覺得 then()
之後要接一堆 function 很醜,也可將其抽出新 function。
12 行
pipe(
addAsync(1),
then(calculate),
otherwise(console.error)
)(1) // ?
如此 then()
只要接 calculate()
即可,可讀性非常高。
propEq()
import { pipe, andThen as then, otherwise, cond, propEq, T, lensProp, set } from 'ramda'
import { resolve } from 'wink-fp'
let data = {
title: 'Speaking JavaScript',
price: 100
}
let fetchObj = o => resolve(o)
let priceLens = lensProp('price')
pipe(
fetchObj,
then(cond([
[propEq('price', 100), set(priceLens, 110)],
[propEq('price', 200), set(priceLens, 220)],
[T, set(priceLens, 330)]
])),
otherwise(console.error)
)(data) // ?
另一個常見的情況是處理 Object,則 cond()
可搭配 propEq()
,至於寫入 Object 則可靠 Lens。
Extract Function
import { pipe, andThen as then, otherwise, cond, propEq, T, lensProp, set } from 'ramda'
import { resolve } from 'wink-fp'
let data = {
title: 'Speaking JavaScript',
price: 100
}
let fetchObj = o => resolve(o)
let priceLens = lensProp('price')
let writeObj = cond([
[propEq('price', 100), set(priceLens, 110)],
[propEq('price', 200), set(priceLens, 220)],
[T, set(priceLens, 330)]
])
pipe(
fetchObj,
then(writeObj),
otherwise(console.error)
)(data) // ?
13 行
let writeObj = cond([
[propEq('price', 100), set(priceLens, 110)],
[propEq('price', 200), set(priceLens, 220)],
[T, set(priceLens, 330)]
])
也可將 then()
之後的 cond()
抽出新 funtion。
19 行
pipe(
fetchObj,
then(writeObj),
otherwise(console.error)
)(data) // ?
如此 then()
只要接 writeObj()
即可,可讀性非常高。
Conclusion
- 若要在 Promise Chain 使用
cond()
有兩種方式:一種是將cond()
躲在then()
內;另一種是將cond()
抽出新 function,最後一次傳給then()
Reference
Ramda, pipe()
Ramda, cond()
Ramda, andThen()
Ramda, propEq()
Ramda, lensProp()
Ramda, set()