【问题标题】:What's the difference between onComplete and flatMap of Future?Future的onComplete和flatMap有什么区别?
【发布时间】:2014-10-14 09:44:40
【问题描述】:

我正在使用 ReactiveMongo 驱动程序编写一个 Scala 应用程序。访问数据库的方法总是返回Future[T]。以下代码段是否等效?

(与onComplete

val results: Future[List[Tag]] = Tags.all.toList
results onComplete {
    case Success(list) => //do something with list
    case Failure(t) => //throw the error
}

(与flatMap

Tags.all.toList.flatMap(list => //do something with list)

有什么区别?

flatMap 不会抛出Failure??而flatMap 是类似onComplete 的回调,还是等到Tags.all.toList 语句未完成?

【问题讨论】:

  • 从签名中可以明显看出:同样尝试 monad,flatMap 不关心失败。这就是 monad 的意义所在:您完整地传递任何错误并仅在管道中没有错误时应用您的操作。只有在最后你才被建议同时抓住错误和成功

标签: scala asynchronous future reactive-programming


【解决方案1】:

如有疑问,请遵循类型。

onComplete 返回Unit,它允许你对Future 结果做一些事情,但它不会返回值

flatMap 允许您对列表进行操作返回一个新的Future

所以flatMap 更强大,因为它允许您链接多个期货,沿途使用它们的值做一些事情,并仅在最后处理失败情况。用 Erik Meijer 的话来说:“它会引导你走上幸福的道路”。

例如你可以这样做

val finalFuture = results
 .flatMap(x => /* do something and return a future */)
 .flatMap(y => /* do something else and return a future */)
 .flatMap(z => /* do something else and return a future */)
 .map(myresult => /* do something */)

如果在此过程中出现问题,链条会提前中断,您将遇到第一个错误。

这允许更好的语法

 val finalFuture = for {
    x <- results
    y <- /* do something and return a future */
    z <- /* do something and return a future */
 } yield something(z)

如果您需要处理失败情况,您现在可以使用onComplete,或者——甚至更好——直接返回Future,因为它已经包含有关异步计算是否成功的信息。

【讨论】:

  • 很好的答案。今天帮助了我。
  • 在这个例子中,finalFuture 返回一个 Future[Nothing] 不管 something(z) 的类型是什么。如果你需要将 something(z): T 传递给期望 T 的东西怎么办?
  • @Azeli finalFuture 的类型取决于某些东西的返回类型。如果某物返回 A,则它是 Future[A]。如果需要将 A 类型的值传递给函数,则需要在 Future 的上下文中执行,即在理解中或直接在地图中。或者,您可以阻止未来并等待其结果,但这很少是一个好策略
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-26
  • 2016-08-16
  • 1970-01-01
  • 2014-02-23
  • 1970-01-01
  • 2020-03-14
  • 2011-06-24
相关资源
最近更新 更多