在同一个 Action.async Scala Play 中调用 2 个 Futures
Call 2 Futures in the same Action.async Scala Play
我是 Scala 的新手 :( 也就是说,我正在与 Play 框架 Action.async 和 Future 调用作斗争。
我想在同一个 Action 中调用 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 来处理 Option 和 Future,但总是会出现这样的错误之一。
然而,在我添加 "Tag" 功能之前,一个 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 个 Futures 并等待它们都计算通过 Ok() 将它们传递到我的页面视图?
非常感谢任何澄清!
您需要 map
和 flatMap
Future
才能异步访问它们的结果。 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-comprehension 来清理它,它是 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
方法。
The flatMap
method takes a function that maps the value to a new future g
, and then returns a future which is completed once g
is completed.
(来自 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
}
}
}
我是 Scala 的新手 :( 也就是说,我正在与 Play 框架 Action.async 和 Future 调用作斗争。
我想在同一个 Action 中调用 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 来处理 Option 和 Future,但总是会出现这样的错误之一。
然而,在我添加 "Tag" 功能之前,一个 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 个 Futures 并等待它们都计算通过 Ok() 将它们传递到我的页面视图?
非常感谢任何澄清!
您需要 map
和 flatMap
Future
才能异步访问它们的结果。 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-comprehension 来清理它,它是 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
方法。
The
flatMap
method takes a function that maps the value to a new futureg
, and then returns a future which is completed onceg
is completed.
(来自 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
}
}
}