gpt4 book ai didi

scala - 摆脱 Scala Future 嵌套

转载 作者:行者123 更新时间:2023-12-02 01:36:33 24 4
gpt4 key购买 nike

当一个函数依赖于一些 future 的结果时,我一次又一次地陷入困境。这通常可以归结为像 Future[Seq[Future[MyObject]]] 这样的结果

为了摆脱这个问题,我现在在辅助函数中使用 Await 来获取非 future 对象并减少嵌套。

看起来像这样

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))
}
})
}

这段代码可以工作,但对我来说它看起来很老套。两次 map 调用是另一个缺陷。我花了几个小时试图弄清楚如何保持完全异步并返回一个简单的 future Seq。如何使用 Play2 最佳实践来解决这个问题?

编辑为了使用例更加清晰:

我有一个来自 mongodb (reactivemongo) 的对象 A,并且想要添加来自对 mongodb getShortInfo 的另一个调用的信息。这是一个经典的“获取此帖子的用户”案例,可以通过 RDBMS 中的联接来解决。由于调用了数据库,getShortInfo自然会产生一个Future。为了减少 findAll 中的嵌套,我使用了 Await()。这是个好主意吗?

findAll 从异步 Play 操作中调用,转换为 Json 并通过线路发送。

def getIdeas(page: Int, perPage: Int) = Action.async {

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

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

简而言之,用例:进行返回序列的 Future 调用,使用结果的每个元素创建另一个 Future 调用,以不应该发生阻塞情况的方式将结果返回到异步操作。

最佳答案

您应该知道的 Future 伴随对象上的两个方便的函数可以在这里提供帮助,第一个也是更容易理解的函数是 Future.sequence。它需要一个 future 序列并返回一个序列的 Future。如果最终得到 Future[Seq[Future[MyObject]]],我们就调用该结果。那么你可以将其更改为 Future[Future[Seq[MyObject]]]result.map(Future.sequence(_))

然后,要折叠任何 X 的 Future[Future[X]],您可以运行“result.flatMap(identity)”,事实上,您可以对任何 M 执行此操作[M[X]] 创建一个 M[X],只要 M 具有 flatMap

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

ideas.map{ Future.traverse(_){ idea =>
/*something that returns a Future[JsObject]*/
} }.flatMap(identity)

但是,很多时候,当您运行 flatMap(identity) 时,您可能会将 map 转换为 flatMap,这里就是这种情况:

ideas.flatMap{ Future.traverse(_) { idea =>
/*something that returns a Future[JsOjbect]*/
} }

关于scala - 摆脱 Scala Future 嵌套,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20276872/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com