摆脱Scala Future嵌套
当函数依赖于未来的某些结果时,我一次又一次地挣扎.
这通常归结为像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.这两个地图调用是另一个缺陷. 编辑 我有一个来自mongodb(reactivemongo)的对象A,并希望将来自另一个调用的信息添加到mongodb getShortInfo.这是一个经典的“获得此帖子的用户”案例,可以通过加入RDBMS来解决. 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.sequence.它需要一个未来的序列并返回一个序列的未来.如果以Future [Seq [Future [MyObject]]]结束,我们可以调用该结果.然后你可以用result.map(Future.sequence(_))将它改为Future [Future [Seq [MyObject]]]
然后为任何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(标识)时,您可能会将地图转换为flatMap,这就是这种情况: ideas.flatMap{ Future.traverse(_) { idea => /*something that returns a Future[JsOjbect]*/ } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |