首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >摆脱Scala未来筑巢

摆脱Scala未来筑巢
EN

Stack Overflow用户
提问于 2013-11-29 00:58:28
回答 2查看 12K关注 0票数 22

当一个函数依赖于一些未来的结果时,我一次又一次地挣扎。这通常归结为未来[Seq[FutureMyObject]]这样的结果。

为了消除这个问题,我现在在一个助手函数中使用Await来获取一个非未来的对象,并减少嵌套。

看上去像这样

代码语言:javascript
运行
复制
def findAll(page: Int, perPage: Int): Future[Seq[Idea]] = {
    val ideas: Future[Seq[Idea]] = collection.find(Json.obj())
    // [...]

    ideas.map(_.map { // UGLY?
      idea => {
        // THIS RETURNED A Future[JsObject] before
        val shortInfo: JsObject = UserDao.getShortInfo(idea.user_id)
        idea.copy(user_data = Some(shortInfo))
      }
    })
}

这段代码很好用,但在我看来却很麻烦。这两个映射调用是另一个缺陷。我花了几个小时试图弄清楚如何保持这个完全异步,并返回一个简单的未来Seq。如何使用Play2最佳实践解决这一问题?

编辑以使使用程序更加清晰:

我有一个来自mongodb (reactivemongo)的对象A,并且希望添加来自对mongodb getShortInfo的另一个调用的信息。这是一个经典的"get user for that post“的案例,它将通过RDBMS中的一个连接来解决。由于对数据库的调用,getShortInfo自然会产生一个未来。为了减少findAll中的嵌套,我使用了Await()。这是个好主意吗

findAll是从异步播放动作调用的,转换为Json并通过线路发送。

代码语言:javascript
运行
复制
def getIdeas(page: Int, perPage: Int) = Action.async {

  for {
    count <- IdeaDao.count
    ideas <- IdeaDao.findAll(page, perPage)
  } yield {
    Ok(Json.toJson(ideas))
  }
}    

因此,我认为从Seq[Future[X]]返回findAll不会带来更好的性能,因为我必须等待结果。这是正确的吗?

总之,usecase :接受返回序列的未来调用,使用结果的每个元素创建另一个未来调用,以不发生阻塞情况的方式将结果返回到异步操作。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-29 03:17:54

未来伙伴对象上的两个方便的函数(您应该知道)在这里可能会有所帮助,第一个更容易理解的函数是Future.sequence。它需要一系列的期货,并返回一个序列的未来。如果以Future[Seq[Future[MyObject]]]结束,让我们将其称为result。然后,您可以将其更改为带有Future[Future[Seq[MyObject]]]result.map(Future.sequence(_))

然后,要折叠任何X的Future[Future[X]],可以运行"result.flatMap(identity)",实际上,只要MflatMap,就可以为任何M[M[X]]创建M[X]

这里的另一个有用的函数是Future.traverse。这基本上是将Seq[A]映射到Seq[Future[B]],然后运行Future.sequence以获得Future[Seq[B]]的结果,因此在您的示例中,您必须:

代码语言:javascript
运行
复制
ideas.map{ Future.traverse(_){ idea =>
    /*something that returns a Future[JsObject]*/
} }.flatMap(identity)

但是,在运行flatMap(identity)时,很多时候可能会将映射转换为flatMap,如下所示:

代码语言:javascript
运行
复制
ideas.flatMap{ Future.traverse(_) { idea =>
    /*something that returns a Future[JsOjbect]*/
} }
票数 50
EN

Stack Overflow用户

发布于 2015-03-25 16:28:41

Akka文件对如何处理期货组合有一个很好的概述。一般而言,它概述了scala.concurrent.Future中的四种方法,这些方法可用于将期货组合简化为一个单独的未来实例:

  • Future.sequence
  • Future.traverse
  • Future.fold
  • Future.reduce
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20276872

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档