我从这个answer学到的andThen
意思是一个函数作曲家。
说那个
f andThen g andThen h
将等于
h(g(f(x)))
这意味着h function
将收到来自g(f(x))
但对于andThen
中的Future
,以下所有关闭,然后始终会收到原始Future
的结果。
Future{
1
}.andThen{ case Success(x) =>
println(x) // print 1
Thread.sleep(2000)
x * 2
}.andThen{ case Success(x) =>
println(x) // print 1
Thread.sleep(2000)
x * 2
}
与
比较val func: Function1[Int, Int] = { x: Int =>
x
}.andThen { y =>
println(y) // print 1
y * 2
}.andThen { z =>
println(z) // print 2
z * 2
}
func(1)
使Future :: andThen(s)从原始Future获得所有相同结果而不是链接Future的原因是什么?我观察到这些链接然后将按顺序执行,因此原因可能不是为了并行目的。
答案 0 :(得分:21)
scala.concurrent.Future
旨在妥协两种异步方法:
将副作用函数应用于此未来的结果,并且 这个未来的结果将带来一个新的未来。
所以andThen
最有可能来自OOP宇宙。要获得与Function1.andThen
类似的类似结果,您可以使用map
方法:
Future(1).map {_ * 2}.map {_ * 2}
andThen
与onComplete
的区别在于一件小事:andThen
的未来仍然会返回相同的结果,但会等到提供的观察者返回或抛出一些东西。这就是文档中写的原因:
此方法允许强制执行回调在a中执行 指定的顺序。
另请注意文档中的第三行:
请注意,如果其中一个链接的andThen回调引发异常, 该异常不会传播到后续的andThen回调。 相反,后续的andThen回调将被赋予原始值 这个未来。
所以它对新Future
的结果完全无效。甚至无法用它的例外来破坏它。这个andThen
和onComplete
只是观察者的顺序和并行绑定。
答案 1 :(得分:1)
让我总结一下这个很好的讨论。
说,我们有tf: Future[T] =...
和两个函数,f: T => U
和g: U => V
我们可以vf: Future[V] = tf map f map g
,与vf: Future[V] = tf map (f andThen g)
在另一个用例中,fp: PartialFunction[T, U]
和gp: PartialFunction[U, V]
,
我们可以运行tf1: Future[T] = tf andThen fp andThen gp
- 这些部分函数将在tf产生的值上调用,没有外部效应 - 只会发生副作用。在调用fp
之前,此序列等待gp
。
另一个未来的操作onComplete就是这样的:拥有f: Try[T] => U
,即使未来以错误结束,调用tf onComplete f
也会调用f
; tf onComplete f
的结果是Unit
类型。
此外,如果您的函数f
生成Future
,则需要使用flatMap
。