Scala期货和`andThen`异常传播 [英] Scala futures and `andThen` exception propagation

查看:140
本文介绍了Scala期货和`andThen`异常传播的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读scala.concurrent.Future模块中的和然后函数的Scala 2.11.8文档,它说如下:

  def andThen [U](pf:PartialFunction [Try [T],U])
(隐式执行器:ExecutionContext):Future [T]




将副作用函数应用于此未来的结果,
返回一个具有此未来结果的新未来。



此方法允许强制执行回调以
指定的顺序执行。 / p>

请注意,如果其中一个链接的andThen回调引发异常,
该异常不会传播到后续的andThen回调。
相反,后续的andThen回调给出了这个未来的原始价值


我不是确定 andThen 没有传播异常的确切含义,并且也没有提供示例。例如,如果我做这样的事情:

  Future.successful {throw new RuntimeException(test)} andThen 
{case _ => println(test)}

在Scala REPL中我得到:

  java.lang.RuntimeException:test 
... 32 elided

因此传播了异常。有人可以提供一个有意义的例子,这究竟意味着什么,以及使用 andThen 使用我希望从中恢复异常的代码是否安全。谢谢。

解决方案

不要在<$ c中抛出异常$ c> Future.successful {} 。



这是正确的方法

 未来{throw new RuntimeException(test)} andThen 
{case _ => println(test)}

你可以理解使用而且使用以下代码行

  Future.successful {1} andThen {case _ => foo} 

REPL

  @ Future.successful {1}然后{case _ => foo} 
res7:未来[Int] =成功(1)

REPL

  @ Future.successful {1} andThen {case _ => println(foo)} 
foo
res8:Future [Int] = Success(1)

REPL

  @ val result = Future.successful {1} andThen { case _ => foo} 
结果:未来[Int] =成功(1)

在上面的例子



我们可以看到执行了andhhen之后的部分函数,​​但忽略了部分函数返回类型。最后,结果输出是 Future 的结果,即 Future [Int]



这意味着 addThen 用于在 Future 之后执行副作用功能已完成。



当未来失败时



REPL

  @ val result = Future {throw new Exception(bar)} andThen {case _ => foo} 
结果:Future [Nothing] =失败(java.lang.Exception:bar)

REPL

  @ val result = Future {throw new Exception(bar)然后{case _ => println(foo)} 
foo
结果:Future [Nothing] = Failure(java.lang.Exception:bar)

未来失败的情况也是如此。然后代码执行,然后执行,但是在byThen之后的代码结果被忽略,最终结果是Future结果。



所以然后用于在Future完成后立即运行副作用代码。 andThen 还将最终输出保持为 Future 的输出。



这就是和然后在标准库中实现的方式。



andThen 位于期货

  def andThen [U](pf:PartialFunction [Try [T],U])(隐式执行器:ExecutionContext):Future [T] = {
val p = Promise [T]()
onComplete {
case r =>尝试pf.applyOrElse [试试[T],任意](r,Predef.conforms [试试[T]])最后完成r
}
p.future
}




1)将副作用函数应用于此未来的结果,并返回这个未来的结果带来了新的未来。




pf 是副作用代码,因为未使用其输出类型(不能使用)。 p.future 是他正在谈论的新未来。
Promise 与之前的 Future 结果一起完成(查看的实现> addThen 上面)



在finally块 p完成r 表示创建了新的Future使用 p.future 并使用之前的结果 r


完成


2)此方法允许强制执行回调以指定顺序执行。


是的。在前一个未来完成后执行 pf 。查看代码 pf 在onComplete块中执行。


3)注意如果其中一个链接的andThen回调引发异常,则该异常不会传播到后续的andThen回调。相反,后续的andThen回调将被赋予此未来的原始值。




r 这是前一个未来的结果给予 pf (看看上面的andThen代码)


I'm reading Scala 2.11.8 documentation of andThen function in the scala.concurrent.Future module and it says the following:

def andThen[U](pf: PartialFunction[Try[T], U])
              (implicit executor: ExecutionContext): Future[T]

Applies the side-effecting function to the result of this future, and returns a new future with the result of this future.

This method allows one to enforce that the callbacks are executed in a specified order.

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.

I'm not sure what does it exactly mean that exceptions are not propagated by andThen and there's also no example provided. For example if I do something like this:

Future.successful { throw new RuntimeException("test") } andThen
                  { case _ => println("test") }

In Scala REPL I get:

java.lang.RuntimeException: test
  ... 32 elided

So the exception was propagated. Could someone please provide a meaningful example what does that exactly means and whether it is safe using andThen with code that my throw exceptions which I would like to recover from. Thank you.

解决方案

Don't throw exception in Future.successful {}.

here is the correct way to do it

Future { throw new RuntimeException("test") } andThen
                  { case _ => println("test") }

You can understand the use of andThen using the following line of code

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)

In the above examples

We can see that partial function after andthen is executed but partial function return type is ignored. Finally the resultant output is result of the Future which is the Future[Int]

This means addThen is used for executing side effecting function just after the Future is completed.

When Future is a Failure

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)

Same is the case when future is a failure. Code after andThen executes and but the result of the code after andThen is ignored and final result is the Future result.

So andThen is used for running side effecting code as soon as Future completes. andThen also keeps the final output as Futures output.

This is how andThen is implemented in Standard library.

andThen resides inside the Future class

 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) Applies the side-effecting function to the result of this future, and returns a new future with the result of this future.

Yes

pf is the side effecting code because its output type is not used (cannot be used). p.future is the new future he is talking about. Promise is completed with the previous Future result (look at the implementation of addThen above)

inside the finally block p complete r means new Future is created using p.future and it is completed using the previous future result which is r

2) This method allows one to enforce that the callbacks are executed in a specified order.

Yes. pf is executed after the previous future is complete. Look at the code pf is executed inside onComplete block.

3) 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.

Yes

r which is the result of the previous future is given to pf (look at the andThen code above)

这篇关于Scala期货和`andThen`异常传播的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆