我是Scala的新手:(那说,我正在与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,但总会有一个错误仍然存在。
然而,在我添加" Tag"之前,未来的一个电话工作正常。功能:
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()将它们传递到我的页面视图?
非常感谢任何澄清!
答案 0 :(得分:3)
您需要map
和flatMap
Future
s才能异步访问其结果。 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))
}
}
}
。这是一个简单的方法:
flatMap
或者你可以使用for-comprehension来清理它,这是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
}
}
}
的语法糖。
map
我还冒昧地简化了findOne
{{1}}结果中的{{1}}。
答案 1 :(得分:2)
您可以使用flatMap
的{{1}}方法。
Future
方法采用将值映射到新的未来flatMap
的函数,然后返回在g
完成后完成的未来。
(来自http://docs.scala-lang.org/overviews/core/futures.html)
所以也许试试:
g
答案 2 :(得分:0)
你可以这样试试。
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
}
}
}