当前位置: 首页 > 知识库问答 >
问题:

在同一个Action.asyncScala Play调用2个期货

乜胜泫
2023-03-14

我是一个Scala新手:(也就是说,我反对Play framework Action.async和Future calls。

我想在同一个动作中调用2个Futures,并等待它们都计算出来,然后将结果发送到我的视图中。

以下是代码:

    def showPageWithTags(category: String) = Action.async {
        val page = PageDAO.findOne(Json.obj("category" -> category)).map {
          case Some(page) => {
            page.content = page.content.byteArrayToString
          }
        }
        val futureTags = ArticleDAO.listTags
        Ok(views.html.web.pages.show(page, futureTags))
   }

通过该定义的功能:

def findOne(id: String): Future[Option[PageModel]]

def listTags: Future[List[String]] 

我得到这个错误:

[error]  found   : Some[A]
[error]  required: models.PageModel
[error]         case Some(page) => {
[error]              ^
.../...
[error]  found   : None.type
[error]  required: models.PageModel
[error]         case None => {
[error]              ^
.../...
[error]  found   : Option[Nothing]
[error]  required: scala.concurrent.Future[play.api.mvc.Result]
[error]       optionPage.map {
[error]                      ^
.../...
[error]  found   : scala.concurrent.Future[Unit]
[error]  required: models.PageModel
[error]         Ok(views.html.web.pages.show(optionPage, futureTags))
[error]                                      ^
.../...
[error]  found   : scala.concurrent.Future[List[String]]
[error]  required: List[String]
[error]         Ok(views.html.web.pages.show(optionPage, futureTags))
[error]                                                  ^

我试着用map、for/yield、foreach来处理期权和期货,但总有一个错误仍然存在。

然而,在我添加“标记”功能之前,未来的一个调用运行良好:

  def showPage(category: String) = Action.async {
    PageDAO.findOne(Json.obj("category" -> category)).map {
      case Some(page) => {
        page.content = page.content.byteArrayToString
        Ok(views.html.web.pages.show(page))
      }
      case None => {
        NotFound
      }
    }
  }

如何在同一个操作中调用2个Futures并等待它们都计算通过Ok()将它们传递给我的页面浏览量?

非常感谢任何澄清!

共有3个答案

孙思源
2023-03-14

可以这样试试。

def showPageWithTags(category: String) = Action.async {

   for{
       pOpt <- PageDAO.findOne(Json.obj("category" -> category))
      futureTags <- ArticleDAO.listTags
      } yield{
          pOpt match {
           case Some(x)=> Ok(views.html.web.pages.show(x.content.byteArrayToString, futureTags))
           case _=> NotFound
                     }              
            }         
}
赵超
2023-03-14

您可以使用< code>Future的< code>flatMap方法。

faceMap方法采用一个函数,该函数将值映射到一个新的未来g,然后返回一个在g完成后完成的未来。

(来自http://docs.scala-lang.org/overviews/core/futures.html)

因此,不妨尝试:

def showPage(category: String) = Action.async {
  ArticleDAO.listTags.flatMap { tags =>
    PageDAO.findOne(Json.obj("category" -> category)).map {
      case Some(page) => {
        page.content = page.content.byteArrayToString
        Ok(views.html.web.pages.show(page, tags))
      }
      case None => {
        NotFound
      }
    }
  }
裴宜春
2023-03-14

您需要映射平面映射未来的以异步访问它们的结果<代码>操作。异步需要一个未来的[结果],因此您必须将未来的映射到该结果。这里有一个简单的方法:

def showPageWithTags(category: String) = Action.async {
    val page = PageDAO.findOne(Json.obj("category" -> category)).map {
      case Some(page) => {
        page.content.byteArrayToString
      }
    }
    val futureTags = ArticleDAO.listTags

    page.flatMap { page =>
        futureTags.map { tags =>
            Ok(views.html.web.pages.show(page, tags))
        }
    }
}

或者您可以使用for理解来清理它,它是平面地图/map的语法糖。

def showPageWithTags(category: String) = Action.async {
    for {
        pageOpt <- PageDAO.findOne(Json.obj("category" -> category))
            .map(_.map(_.content.byteArrayToString))
        tags <- ArticleDAO.listTags
    } yield {
        pageOpt.map { page =>
            Ok(views.html.web.pages.show(page, tags))
        } getOrElse {
            NotFound
        }
    }
}

我还擅自简化了您在< code>findOne结果上的< code >地图。

 类似资料:
  • 问题内容: 在Bruce Eckel的“ Thinking In Java,第四版”的第428页(有关类型信息的章节)中,具有以下示例: 也许我有点累,但是我看不到add()方法中对add()的调用是如何工作的。我一直认为它应该有一个引用,或者是一个静态方法(并且我在ArrayList或List中找不到静态add())。我想念什么? 我只是为自己测试,发现这可行: 问题答案: Java为这样的方法

  • 我想在同一框架中使用2个面板。但是button不起作用了?我该怎么做?我想在一个面板上放几个按钮,另一个面板会做一些其他的事情。

  • 我是RxJava的新手,面临以下问题: 我有两个可完成的对象来存储一些数据。我想触发第一个,然后在第一个成功完成后再启动第二个。应该阻止对第二个Completable的调用,直到第一个完成并成功为止。此外,如果第一个完成时出现错误,则还应跳过另一个。 通过查看留档和其他SO问题,或似乎对我有用。但是在手动测试和单元测试中,我可以看到第二个可完成项是与第一个并行触发的:/ 首先完成 第二个可完成 尝

  • 在这个组件中,我在顶部有一个图像,然后在底部有两个其他组件(在内部),它们显示为不同的行。我想把另外两个项目(一个网格和一个图表)放在单行中,我已经尝试过使用flex direction,但它似乎对我不起作用。这可能是因为我已经在父组件中使用了。 ItemsContainer: 我如何修复这一点,使网格出现在左边,图表出现在右边,但在同一行/行? 下面是ItemContainer内部两个主要子组件

  • UPATE启动 正确答案如下: 是否可以不使用完成块在UIView上执行多个动画 没必要读这个。 上端 我有类似的问题,UIView animateWithDuration会立即返回,但我不能使用完成块,因为我的动画有不同的功能。 但确实想要动画相同的对象。 我在做纸牌游戏,所以我在屏幕上移动纸牌,但在移动之前,我也有一些游戏逻辑。这就是为什么我可以方便地单独制作动画。 如何解决这个问题? @Fo

  • 基本上我有: 错误:只有在显式请求批注处理时才接受类名“test” 非常感谢所有的回复:)