scala 为什么Future 的andThen 不链接结果?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30659427/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does the andThen of Future not chain the result?
提问by Chen OT
The andThenmeaning I learned from this answeris a function composer.
andThen我从这个答案中学到的意思是函数作曲家。
Say that
比如说
f andThen g andThen h
will equal to
将等于
h(g(f(x)))
This implies the h functionwill receive input from g(f(x))
这意味着h function将接收来自g(f(x))
But for the andThenin Future, all the closure of the following andThen always receives the result from the original Future.
但是对于andThenin Future,后面andThen的所有闭包总是从原来的接收结果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
}
compare to
相比于
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)
What is the reason to make Future::andThen(s) receive all the same result from original Future instead of chaining Future? I've observed that these chained andThen will be executed sequentially, so the reason may not be for parallel purpose.
让 Future::andThen(s) 从原始 Future 接收所有相同结果而不是链接 Future 的原因是什么?我观察到这些链接的 andThen 将按顺序执行,因此原因可能不是出于并行目的。
回答by Odomontois
scala.concurrent.Futureis designed as compromise of two asynchronous approaches:
scala.concurrent.Future被设计为两种异步方法的折衷:
- Object-oriented observerwhich allows binding of asynchronous handlers
- Functional monadwhich offers rich functional composition capabilities.
Reading Future.andThen's docs:
Applies the side-effecting function to the result of this future, and returns a new future with the result of this future.
将副作用函数应用于此未来的结果,并使用此未来的结果返回一个新的未来。
So andThenis most likely from OOP universe. To gain similar similar result to Function1.andThenyou could use S)(implicitexecutor:scala.concurrent.ExecutionContext):scala.concurrent.Future[S]" rel="noreferrer">mapmethod :
所以andThen很可能来自 OOP 世界。要获得与Function1.andThen您相似的结果,可以使用S)(implicitexecutor:scala.concurrent.ExecutionContext):scala.concurrent.Future[S]" rel="noreferrer">map方法:
Future(1).map {_ * 2}.map {_ * 2}
andThendiffers from onCompletewith one little thing: resulting Future of andThenstill returning same result, but will wait until supplied observer will return or throw something. That's why there is written in the docs:
andThen与onComplete一件小事不同:结果 FutureandThen仍然返回相同的结果,但会等到提供的观察者返回或抛出一些东西。这就是为什么在文档中写道:
This method allows one to enforce that the callbacks are executed in a specified order.
此方法允许强制以指定的顺序执行回调。
Also note third line from docs:
还要注意文档中的第三行:
Note that if one of the chained andThen callbacks throws an exception, that exception is not propagated to the subsequent andThen callbacks. Instead, the subsequent andThen callbacks are given the original value of this future.
请注意,如果链接的 andThen 回调之一抛出异常,则该异常不会传播到后续的 andThen 回调。相反,随后的 andThen 回调被赋予这个未来的原始值。
So it' completely do nothing with new Future's result. Could not even spoil it with it's ownt exception. This andThenand onCompletejust sequential and parallel binding of observers.
所以它对 newFuture的结果完全没有任何作用。甚至不能用它自己的例外来破坏它。这andThen和onComplete观察者的顺序和并行绑定。
回答by Vlad Patryshev
Let me sum up this nice discussion.
让我总结一下这个不错的讨论。
Say, we have tf: Future[T] =..., and two functions, f: T => Uand g: U => V
说,我们有tf: Future[T] =..., 和两个函数,f: T => U和g: U => V
We can do vf: Future[V] = tf map f map g, same asvf: Future[V] = tf map (f andThen g)
我们可以做vf: Future[V] = tf map f map g,就像vf: Future[V] = tf map (f andThen g)
In another use case, having fp: PartialFunction[T, U]and gp: PartialFunction[U, V],
we can run tf1: Future[T] = tf andThen fp andThen gp- these partial functions will be called on the value that tf produces, with no outside effect - only side effects happen. This sequence waits for fpbefore calling gp.
在另一个用例中,有fp: PartialFunction[T, U]and gp: PartialFunction[U, V],我们可以运行tf1: Future[T] = tf andThen fp andThen gp- 这些部分函数将在 tf 产生的值上调用,没有外部影响 - 只有副作用发生。这个序列fp在调用之前等待gp。
Yet another future operation, onComplete, works like this: having f: Try[T] => U, the call tf onComplete fwill call feven if the future ended with an error; the result of tf onComplete fis of type Unit.
另一个未来操作 onComplete 是这样工作的:拥有f: Try[T] => U,即使未来以错误结束,调用tf onComplete f也会调用f;的结果tf onComplete f是 类型Unit。
Also, if your function fproduces a Future, you will need to use flatMap.
此外,如果您的函数f生成Future,则需要使用flatMap.

