Scala期货和`andThen`exception传播
我在scala.concurrent.Future模块中阅读了Scala 2.11.8和andThen
函数的文档,它说如下:
def andThen[U](pf: PartialFunction[Try[T], U]) (implicit executor: ExecutionContext): Future[T]
将副作用函数应用于此未来的结果,并返回具有此未来结果的新未来。
此方法允许强制执行回调以指定顺序执行。
请注意,如果链接的andThen回调之一抛出exception,则该exception不会传播到后续的andThen回调。 相反,后续的andThen回调将被赋予此未来的原始值。
我不确定它是什么意思是exception不会被传播, andThen
也没有提供示例。 例如,如果我做这样的事情:
Future.successful { throw new RuntimeException("test") } andThen { case _ => println("test") }
在Scala REPL中我得到:
java.lang.RuntimeException: test ... 32 elided
所以exception被传播了。 有人可以提供一个有意义的例子,这究竟意味着什么,以及是否安全使用andThen
代码,我抛出exception,我想从中恢复。 谢谢。
不要在Future.successful {}
throw
exception。
这是正确的方法
Future { throw new RuntimeException("test") } andThen { case _ => println("test") }
您可以使用以下代码行来理解和使用
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
完成后执行副作用function。
当未来是一个失败
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)
未来是失败的情况也是如此。 然后执行代码,然后执行,然后忽略andThen之后的代码结果,最终结果是Future结果。
因此,当Future完成后, andThen
用于运行副作用代码。 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
的实现)
在finally块内部p complete r
意味着使用p.future
创建新的Future,并使用之前的结果(即r
2)此方法允许强制执行回调以指定顺序执行。
是。 pf
在前一个未来完成后执行。 查看代码pf
是在onComplete块中执行的。
3)注意,如果链接的andThen回调之一抛出exception,则该exception不会传播到后续的andThen回调。 相反,后续的andThen回调将被赋予此未来的原始值。
是
r
是前一个未来的结果给pf
(看看上面的andThen代码)
我认为类型签名是最好的文档。 如你所见, andThen
接受T => U
(省略PF和为简单起见),并给出Future[T]
。 所以你可以想到它,然后andThen
执行一些效果并回归原始的未来。 因此,如果你的部分function上升exception,它将不会传播给其他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,以便在程序结束之前完成未来。 所以你可能正确理解了一切。