当前位置: 首页 > 知识库问答 >
问题:

Scala 期货和'andThen'异常传播

甘明朗
2023-03-14

我正在阅读Scala 2.11.8留档的函数在scala.concurrent.Future模块,它说:

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

将副作用函数应用于这个未来的结果,并返回一个包含这个未来的结果的新的未来。

这个方法允许强制回调以指定的顺序执行。

请注意,如果其中一个链式第四个回调引发异常,则该异常不会传播到后续的第四个调用。相反,随后的第四次回调将被赋予此未来的原始值。

我不确定< code >和不传播异常到底是什么意思,也没有提供示例。例如,如果我做这样的事情:

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

在斯卡拉REPL,我得到了:

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

所以异常被传播。有人能提供一个有意义的例子吗?这到底是什么意思?对抛出异常的代码使用< code > then 是否安全?谢谢你。

共有2个答案

壤驷乐邦
2023-03-14

我认为类型签名是最好的文档。如您所见,并且Then接受T =

  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)

再读一遍你的例子。我想你只是忘了线。睡到最后,让未来在节目结束前完成。所以你可能对一切都理解正确。

云和同
2023-03-14

以后不要<code>抛出<code>异常。成功{}。

下面是正确的方法

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

您可以使用以下代码行了解andRe的使用

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)

在上面的例子中

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

这意味着< code>addThen用于在< code>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)

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

因此,andThen 用于在 Future 完成后立即运行副作用代码。并且Then还将最终输出保留为Future的输出。

这就是andTime在标准库中的实现方式。

并且位于未来类中

 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) 将副作用函数应用于此future的结果,并使用此future结果返回一个新future。

对呀

pf是副作用代码,因为它的输出类型没有被使用(不能被使用)。p.future是他所说的新未来。Promise是用前面的Future结果完成的(看看上面add的实现)

在finally块中,p完成r意味着使用p创建新的未来。future,并使用先前的future结果(即<code>r

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

是的。您可以使用多个and And调用链接多个回调,并且这些回调按照and And调用的顺序一个接一个地执行。这与您可以多次使用它来注册多个回调的on完成方法相比,但这些回调的顺序是不确定的。

3)请注意,如果链接的andAnd回调之一抛出异常,则该异常不会传播到后续的andAnd回调。相反,后续的andAnd回调被赋予这个未来的原始值。

r是上一个未来的结果,给出给pf(看上面的andAnd代码)

 类似资料:
  • 我正在努力理解这个概念。我清楚地了解期货是什么。我对Promises有点困惑。下面的代码片段: 现在,以下两个代码片段之间有什么区别? 和 我对第一个的理解是,p成功将完成与该p相关的未来计算。计算是异步的吗?这与使用 Future 块完成与 Promise p 关联的 Future f 的第二个代码片段有何不同?

  • 我是Scala未来的新手,我还没有找到问题的解决方案。我正在努力实现以下目标(总体描述:努力获取一个酒店列表的客人列表,分别查询每个酒店): < li >对另一个API进行n次调用,每次调用都超时 < li >合并所有结果(将列表转换为包含所有元素的列表) < li >如果单个调用失败,记录错误并返回一个空列表(本质上,在这种情况下,如果我得到部分结果总比没有结果好) < li >理想情况下,如果

  • 我使用scala futures异步提交了1000份工作。我还实现了一个由并发阻塞队列支持的ThrottledExecutionContext,这样它一次最多只能运行100个作业,并将其余的放入队列中。这是一个阻塞操作,因为它涉及调用第三方服务本身。当其中一个抛出异常时,我需要重试整个操作(1000个作业)或者跳过整个批处理。当某些期货仍在运行时,我不能重试。我有办法知道在任何给定的时间点有多少作

  • 我正在使用: Scala 2.10 游戏2.1 目前,我正在使用 类,但我愿意尝试另一个 API。 我很难将多个期货的结果组合成一个列表[(String, String)]。 以下 方法成功地将单个 Future 的结果返回到 HTML 模板: 方法执行 Web 服务 API 调用并返回 Future[play.api.libs.ws.Response]。方法 向 HTML 模板返回 List[(

  • Java 8的< code > CompletableFuture . allof(CompletableFuture 如果我的一个期货异常完成,那么< code > completablefuture . allof 会在抛出< code>CompletionException之前等待其余期货完成,还是会取消其余期货? 如果它等待所有期货完成,有没有办法让它在任何期货抛出异常并取消剩余期货时立即

  • 在用收益结构组合期货时,有些有副作用,有些没有,我引入了竞争条件,因为取决于副作用的未来并没有将副作用的结果作为论据。 简而言之: 未来b读取由来自未来a的副作用改变的值,但是未来a不明确依赖于未来b的结果,因此可能在b完成读取之前发生。 为了解决这个问题,我的同事引入了一个虚拟函数,将b的结果作为参数并简单地将其丢弃。这样做是为了使依赖显式化。 实际代码如下: 在这种情况下,未来 b 为 带哑参