繁体   English   中英

在同一Action.async Scala中调用2个期货

[英]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进行mapflatMap以便异步访问其结果。 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

您可以使用FutureflatMap方法。

flatMap方法采用一个将值映射到新的Future g的函数,然后返回一个一旦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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM