我在scala.concurrent.Future模块中阅读了andThen
函数的Scala 2.11.8文档,并说明了以下内容:
def andThen[U](pf: PartialFunction[Try[T], U])
(implicit executor: ExecutionContext): Future[T]
将副作用函数应用于此未来的结果,并且 这个未来的结果将带来一个新的未来。
此方法允许强制执行回调在a中执行 指定的顺序。
请注意,如果其中一个链接的andThen回调引发异常, 该异常不会传播到后续的andThen回调。 相反,后续的andThen回调将被赋予原始值 这个未来。
我不确定andThen
不会传播异常的确切含义是什么,也没有提供示例。例如,如果我这样做:
Future.successful { throw new RuntimeException("test") } andThen
{ case _ => println("test") }
在Scala REPL中,我得到:
java.lang.RuntimeException: test
... 32 elided
因此传播了异常。有人可以提供一个有意义的例子,这究竟意味着什么,以及使用andThen
代码是否安全,我抛出了我想从中恢复的异常。谢谢。
答案 0 :(得分:3)
throw
中不要Future.successful {}
例外。
这是正确的方法
Future { throw new RuntimeException("test") } andThen
{ case _ => println("test") }
您可以使用以下代码行
了解andThen
的使用情况
Future.successful { 1 } andThen { case _ => "foo" }
<强> REPL 强>
@ Future.successful { 1 } andThen { case _ => "foo" }
res7: Future[Int] = Success(1)
<强> REPL 强>
@ Future.successful { 1 } andThen { case _ => println("foo") }
foo
res8: Future[Int] = Success(1)
<强> REPL 强>
@ val result = Future.successful { 1 } andThen { case _ => "foo" }
result: Future[Int] = Success(1)
在上面的例子中
我们可以看到执行了andhhen之后的部分函数,但忽略了部分函数返回类型。最后,结果输出是Future
的结果,即Future[Int]
这意味着addThen
用于在Future
完成后执行副作用功能。
当未来是失败
<强> REPL 强>
@ val result = Future { throw new Exception("bar") } andThen { case _ => "foo" }
result: Future[Nothing] = Failure(java.lang.Exception: bar)
<强> REPL 强>
@ val result = Future { throw new Exception("bar") } andThen { case _ => println("foo") }
foo
result: Future[Nothing] = Failure(java.lang.Exception: bar)
未来失败的情况也是如此。然后执行代码,然后执行,但是在byThen之后的代码结果被忽略,最终结果是Future结果。
因此,andThen
用于在Future完成后立即运行副作用代码。 andThen
也将最终输出保持为Future
的输出。
这是andThen
在标准库中的实现方式。
andThen
位于Future
类
def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): Future[T] = {
val p = Promise[T]()
onComplete {
case r => try pf.applyOrElse[Try[T], Any](r, Predef.conforms[Try[T]]) finally p complete r
}
p.future
}
1)将副作用函数应用于此未来的结果,并返回具有此未来结果的新未来。
是
pf
是副作用代码,因为它的输出类型未被使用(不能使用)。 p.future
是他正在谈论的新未来。
Promise
已完成上一个Future
结果(请查看上面addThen
的实施情况)
p complete r
中的表示使用p.future
创建新的Future,并使用之前的r
2)此方法允许强制执行回调以指定顺序执行。
是。在前一个未来完成后执行pf
。查看代码pf
是在onComplete块内执行的。
3)请注意,如果链接的andThen回调之一抛出异常,则该异常不会传播到后续的andThen回调。相反,后续的andThen回调将被赋予此未来的原始值。
是
r
这是前一个未来的结果,是pf
(请查看上面的andThen代码)
答案 1 :(得分:1)
我认为类型签名是最好的文档。
如您所见,andThen
接受T => U
(省略PF并尝试简化),并返回Future[T]
。
所以你可以想到它,andThen
执行一些效果并返回原始未来。因此,如果您的部分函数提升异常,它将不会传播到其他andThen
并且它们将对原始未来起作用:
import scala.concurrent.ExecutionContext.Implicits.global
Future{ 2 } andThen {
case _ => throw new RuntimeException("test")
} andThen {
case v ⇒ println("After exception"); println(v)
}
Thread.sleep(500)
打印:
java.lang.RuntimeException: test
After exception
Success(2)
PS。再次阅读您的示例。我想你最后忘记了Thread.sleep,以便在程序结束之前完成未来。所以你可能正确地理解了一切。