当函数依赖于未来的某些结果时,我一次又一次地挣扎 . 这通常归结为像Future [Seq [Future [MyObject]]]这样的结果
为了摆脱这一点,我现在在辅助函数中使用Await来获取非未来对象并减少嵌套 .
看起来像这样
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))
}
})
}
这段代码有效,但对我来说它看起来很hacky . 这两个 Map 调用是另一个缺陷 . 我花了好几个小时试图弄清楚如何保持这种完全异步并返回一个简单的未来Seq . 如何使用Play2最佳实践解决这个问题?
Edit 使用例更清晰:
我有一个来自mongodb(reactivemongo)的对象A,并希望将来自另一个调用的信息添加到mongodb getShortInfo . 这是一个经典的"get user for this post"案例,可以通过RDBMS中的连接来解决 . 由于对db的调用, getShortInfo 自然会产生Future . 为了减少 findAll 中的嵌套,我使用了Await() . 这是一个好主意吗?
findAll 从异步Play动作调用,转换为Json并通过线路发送 .
def getIdeas(page: Int, perPage: Int) = Action.async {
for {
count
ideas
} yield {
Ok(Json.toJson(ideas))
}
}
所以我认为从findAll返回 Seq[Future[X]] 将不会带来更好的性能,因为我必须等待结果 . 它是否正确?
简而言之:使用Future调用返回一个Sequence,使用结果的每个元素创建另一个Future调用,以不会发生阻塞情况的方式将结果返回给异步操作 .