摆脱 Scala Future 嵌套

2024-01-01

当一个函数依赖于一些未来的结果时,我一次又一次地陷入困境。 这通常可以归结为像 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))
      }
    })
}

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

Edit为了使用例更加清晰:

我有一个来自 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))
  }
}    

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

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


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

然后折叠一个Future[Future[X]]对于任何 X,您可以运行“result.flatMap(identity)”,事实上,您可以对任何 X 执行此操作M[M[X]]创建一个M[X]只要M has 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) 时,您可能会将地图转换为 flatMap,这里就是这种情况:

ideas.flatMap{ Future.traverse(_) { idea =>
    /*something that returns a Future[JsOjbect]*/
} }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

摆脱 Scala Future 嵌套 的相关文章

随机推荐

  • 如何让表头透明?

    我花了很多时间来解决这个问题 但仍然不明白我做错了什么 我需要我的标题是透明的 没有背景 举个例子 但我不明白透明度是如何工作的 我已经尝试了一切 但它总是白色的 透明度仅适用于文本 帮帮忙 我真的很期待 body margin 0 fon
  • 弹性容器内的居中元素正在增长并溢出到顶部之外[重复]

    这个问题在这里已经有答案了 我一定忘记了垂直和水平居中弹性盒的一些基本知识 容器位于具有垂直滚动的父级内 当容器变得太高时 它会超出父级顶部 从而剪切内容 底部保持原状 尝试调整视图的高度或添加更多线条以查看其实际效果 body html
  • 无法从 Microsoft Dynamics CRM WebAPI 调用 BulkDelete 操作

    我正在尝试致电批量删除 操作 https learn microsoft com en us previous versions dynamicscrm 2016 developers guide mt491158 v 3Dcrm 8 本地
  • 更改分支点

    我有一个分支叫feature它有一些提交 分支及其提交仍然位于我的机器本地 还没有push编辑到公共存储库 该图看起来像 A B C D E F G master P Q R feature 现在我意识到我应该建立分支feature脱离先前
  • 在测试中覆盖调试模块

    我有一个 Gradle 应用程序 其项目结构类似于杰克 沃顿的 u2020 https github com jakewharton u2020 src androidTest debug main release 在我的应用程序类中 我构
  • Alamofire 使用 PUT 上传图像

    我目前正在尝试使用预先签名的网址将图像上传到亚马逊 它的工作方式是 我发出 GET 请求来获取预签名的 URL 然后发出 PUT 请求以使用 GET 请求返回的 url 上传图像 这两条规则是 Content Type 必须是 image
  • 用于压缩的 WCF 自定义绑定

    遵循样本压缩 http msdn microsoft com en us library ms751458 aspx由微软 我已将编码器 编码器工厂和绑定元素添加到我的解决方案中 与他们的示例的不同之处在于 我们不通过配置文件 要求 注册端
  • 将 MVC3 应用程序发布到 IIS 错误 - Web 服务器配置为不列出此目录的内容

    我将网站发布到 C inetpub wwwroot Sem App 并创建了一个物理路径为 C inetpub wwwroot Sem App 和端口 84 的网站 当我在http localhost 84 我收到以下错误 HTTP Err
  • 隐藏 MasterDetailPage 上的导航栏

    我有一个 MasterDetailPage 包含以下构造函数 public MainPage NavigationPage SetHasNavigationBar this false NavigationPage SetHasBackBu
  • Firebase - 在 Node.js 服务器上创建用户

    我们有一个使用 Firebase v2 的大型 SPA 我们想升级到新的 API 但遇到以下问题 由于应用程序相当大 我们开发了许多集成测试 对于这些测试 我们总是需要重置数据库并将其初始化为某些用户存在的状态 然而 我们发现确实不再有在服
  • 如何使用 python 和 openssl 验证 webhook 签名

    我正在尝试验证传入的 webhook 但到目前为止生成的哈希值与 api 生成的测试哈希值不匹配 文档列出了以下 Ruby 示例 但我使用的是 Python Django 因此任何 转换 此函数的帮助将不胜感激 红宝石函数 request
  • 路由“ActivityFeed”的组件必须是 React 组件

    我在这里查看了关于类似问题的各种类似帖子 但没有一个答案为我解决了这个问题 这是完整的错误 所以在我的src navigation feed stack js它的定义如下 import React from react import Sta
  • 通过 Button 向 Php 函数传递值

    我是 php 初学者 目前正在管理面板上工作 你可以看到我的管理面板页面 问题是我想通过这两个按钮传递序列号以进一步执行 但我找不到如何发送 value编辑和删除特定行 div strong h3 Admin page h3 strong
  • 检测当前页面是否加载AngularJS的方法

    如何检测当前页面是否加载了 AngularJS 我想从 CDN 加载 AngularJS 如果失败 我想从 LocalServer 加载 以下脚本针对 JQuery 执行此操作
  • Spring中ApplicationContext.xml和属性文件的位置

    在我的应用程序中 我放置了ApplicationContext xml文件放在 src 中 项目运行良好 我们可以放置ApplicationContext xml在我们的 WebContent 或 Web Inf 文件夹中 我还想知道是否可
  • 搜索具有不同列的多个表

    我想为我的网站建立一个搜索引擎 我的数据库表列表如下 d name 我需要搜索two列 em 我需要搜索one column seri 我需要搜索one column topics 我需要搜索one column 许多其他表的数量是动态的
  • 行在 Android 布局中无法正确呈现。按钮似乎是问题

    我是 Android 开发新手 我的 XML 布局遇到了问题 当我只有包含文本和 edittext 的行时 布局保持正常 但是一旦我将带有按钮的行放在下面 下面的行就会消失在屏幕下方 这些行彼此渲染得很远 我做错了什么 我的应用程序的 iP
  • java CompletableFuture 相当于 scala Future 的救援和句柄是什么

    我看到CompletableFuture有一个方法handle与 scala 相同Future s handle基本上将成功和异常全部转换为成功map and flatMap上游 或thenApply and thenCompose在Jav
  • Go:同一包中未定义的函数[重复]

    这个问题在这里已经有答案了 我已经开始 Go 并试图遵循这个tutorial https www activestate com blog 2017 04 creating web app using golang gorilla web
  • 摆脱 Scala Future 嵌套

    当一个函数依赖于一些未来的结果时 我一次又一次地陷入困境 这通常可以归结为像 Future Seq Future MyObject 这样的结果 为了摆脱这个问题 我现在在辅助函数中使用 Await 来获取非未来对象并减少嵌套 看起来像这样