【问题标题】:Why does the andThen of Future not chain the result?为什么 Future 的 andThen 不链接结果?
【发布时间】:2015-08-19 23:38:06
【问题描述】:

我从这个answer学到的andThen的意思是一个函数作曲家。

说出来

f andThen g andThen h

将等于

h(g(f(x)))

这意味着h function 将接收来自g(f(x)) 的输入

但是对于Future中的andThen,后面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
}

比较

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)

让 Future::andThen(s) 从原始 Future 而不是链接 Future 接收所有相同结果的原因是什么?我观察到这些链接的 andThen 将按顺序执行,因此原因可能不是出于并行目的。

【问题讨论】:

    标签: scala future


    【解决方案1】:

    scala.concurrent.Future 被设计为两种异步方法的折衷方案:

    1. 面向对象的observer 允许绑定异步处理程序
    2. 函数式monad,提供丰富的函数式组合能力。

    阅读Future.andThen's docs

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

    所以andThen 很可能来自 OOP 世界。要获得与Function1.andThen 相似的结果,您可以使用map 方法:

    Future(1).map {_ * 2}.map {_ * 2}
    

    andThenonComplete 有一点不同:andThen 的结果 Future 仍然返回相同的结果,但会等到提供的观察者返回或抛出一些东西。这就是文档中写的原因:

    此方法允许强制回调在一个 指定顺序。

    还要注意文档中的第三行:

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

    所以它对新的Future 的结果完全没有任何作用。甚至不能用它自己的例外来破坏它。这andThenonComplete 只是观察者的顺序和并行绑定。

    【讨论】:

    • 我可以说它是 onComplete 的另一个版本,但返回“this”,以便它可以以链式方式绑定多个“观察者”回调处理程序?
    • @ChenOT 是的。差不多
    • @但有一点不同。我会将其添加到 asnwer
    • 哦哦!与 onComplete 返回 Unit 不同,可链接的 andThen 意味着这些 andThen 闭包将按顺序执行
    • onSuccess、onFailure、onComplete、andThen是一组绑定Observer回调函数的函数,可能是副作用过程。而另一组map,flatMap,fallbackTo,recover,...是future composer,将future的结果链起来传播到尾部。我说的对吗?
    【解决方案2】:

    让我总结一下这次精彩的讨论。

    比如说,我们有tf: Future[T] =...,还有两个函数f: T => Ug: U => V

    我们可以做vf: Future[V] = tf map f map g,和vf: Future[V] = tf map (f andThen g)一样

    在另一个用例中,有fp: PartialFunction[T, U]gp: PartialFunction[U, V], 我们可以运行tf1: Future[T] = tf andThen fp andThen gp - 这些部分函数将在 tf 产生的值上调用,没有外部影响 - 只有副作用发生。此序列在调用gp 之前等待fp

    另一个未来的操作,onComplete,像这样工作:拥有f: Try[T] => U,调用tf onComplete f 将调用f,即使未来以错误结束; tf onComplete f 的结果是 Unit 类型。

    另外,如果您的函数 f 产生 Future,您将需要使用 flatMap

    【讨论】:

      猜你喜欢
      • 2021-08-15
      • 1970-01-01
      • 2014-03-03
      • 1970-01-01
      • 2014-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多