[英]Call 2 Futures in the same Action.async Scala Play
我是Scala的newby :(就是说,我正在与Play框架Action.async和Future调用作斗争。
我想在同一操作中调用2个期货,并等到它们都计算出结果后再发送给我。
这是代码:
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来处理Option和Future,但始终存在这种错误之一。
但是,在我添加“标记”功能之前,一个Future呼叫运行良好:
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个期货并等待它们都计算出通过Ok()将它们传递到我的页面视图中?
非常感谢任何澄清!
您需要对Future
进行map
和flatMap
以便异步访问其结果。 Action.async
需要Future[Result]
,因此您必须将Future
映射到该对象。 这是一个简单的方法:
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- flatMap
进行整理,这是flatMap
/ 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
}
}
}
我还自由地简化了findOne
结果上的map
。
您可以使用Future
的flatMap
方法。
flatMap
方法采用一个将值映射到新的Futureg
的函数,然后返回一个一旦g
完成就完成的Future。
(来自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
}
}
}
您可以这样尝试。
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
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.