我正在使用Fluture提取期货。
假设我有一个发出GET请求的函数。此功能可以成功或失败。
发出请求后,如果成功,则打印一条消息,如果失败,则记录错误并执行命令。
axios.get(endpoint, { timeout: timeoutMs })
.fold(
err =>
logger.errorAsync( err )
.chain( ( ) => cmd.getAsync("pm2 restart app")),
response => logger.infoAsync( "Great success!" )
);
我一直在阅读API,发现bimap
和fold
都将函数应用于成功和失败:
bimap :根据存在的值,将左功能映射到拒绝值,或者将右功能映射到分辨率值。
fold (折叠):将左功能应用于拒绝值,或者将右功能应用于分辨率值,具体取决于存在的值,然后解析结果。
如果您敏锐的眼睛,您将知道我的示例无效。我需要使用bimap
,但我不明白为什么。
bimap
,何时应使用fold
?答案 0 :(得分:1)
一个人可能会使用bimap
在单个步骤中同时映射拒绝和分辨率,而Future
将保持被拒绝< / em>或已解决,并进行了新的计算。
另一方面,fold
将同时处理拒绝和分辨率,以始终产生分辨率(您可以折叠两种情况都归为决议之一)。可以使用fold
将两个结果都包装为另一种类型(例如Future Either a b
)或将任何分支视为成功。
因此,bimap
与fold
有所不同,因为第一个将两种情况都映射,第二种将两种情况都转化为决议。
bimap
:const flag = true
const eventualNumber1 = !flag ? Future.reject (1) : Future.of (2)
const eventualNumber2 = Future.bimap (x => x * 2) (x => x + 1) (eventualNumber1)
// it'll output 3.
Future.fork (console.log) (console.log) (eventualNumber2)
fold
:const flag = false
const eventualNumber1 = !flag ? Future.reject (1) : Future.of (2)
const eventualNumber2 = Future.fold (x => x * 2) (x => x + 1) (eventualNumber1)
// It'll output 2 even when the Future represents a rejection
Future.value (console.log) (eventualNumber2)
请注意,fold
是如何完全保证eventualNumber2
是决议,所以我使用Future.value
仅处理决议!
答案 1 :(得分:1)
让我们首先检查它们各自的类型签名:
bimap :: (a -> c) -> (b -> d) -> Future a b -> Future c d
fold :: (a -> c) -> (b -> c) -> Future a b -> Future d c
差别很小,但很明显。有两个主要区别:
bimap
中,两个
函数允许返回不同的类型。在fold
中,两个函数
必须返回相同类型的值。bimap
中,您返回一个Future,其中
拒绝包含从左函数返回的类型的值,
并且分辨率包含从右侧返回的类型的值
功能。在fold
中,拒绝端包含一个全新的类型变量,该变量
尚未受到限制,并且分辨率方面包含
这两个函数都由 返回。那是一个相当大的数目,并且可能很难解析。我将尝试在图表中将其可视化。
对于bimap
,如下所示。这两个分支不相互作用:
rej(x) res(y)
| |
| |
bimap(f)(g): f(x) g(y)
| |
V V
对于fold
,拒绝分支类型为“停止”,而解决分支将
继续使用f(x)
的返回值或 g(y)
的返回值:
rej(x) res(y)
| |
| |
fold(f)(g): -> f(x)*g(y)
|
V
您随时可以使用bimap
来更改拒绝原因和
同时显示分辨率值。做bimap (f) (g)
就像做
compose (mapRej (f)) (map (g))
。
只要您想将拒绝项移至解决方案中,就可以使用fold
科。就您而言,这就是您想要的。您的示例不这样做的原因
之所以工作,是因为您必须拥有未来的未来
展平:
axios.get(endpoint, { timeout: timeoutMs })
.fold(
err =>
logger.errorAsync( err )
.chain( ( ) => cmd.getAsync("pm2 restart app")),
response => logger.infoAsync( "Great success!" )
)
.chain(inner => inner); //<-- Flatten
在函数式编程中使Monad变平滑很常见,通常
称为join
,可以这样实现:
const join = chain(x => x)