Play 2.2 -Scala - 如何在Controller Action中链接Futures

时间:2013-10-23 16:36:00

标签: scala playframework future playframework-2.2

我有3个类型为Response的期货。第一个未来返回一个JsValue,它定义是否将执行未来2和未来3,或者只执行将来的3。

伪代码: 如果未来1那么{future2和future 3} 别的未来3

我试图在游戏框架中执行此操作,这意味着为了使用后期的结果,我无法使用onSuccess,onFailure和onComplete,因为所有这些都返回Unit而不是最后一个实际的JsValue。 / p>

我尝试使用map()和然后尝试做这个,但我是Scala noob,我想我无法做到这一点,因为我总是错过了一点点。这是我目前的做法不起作用!

def addSuggestion(indexName: String, suggestion: String) = Action.async {
  val indexExistsQuery: IndexExistsQuery = new IndexExistsQuery(indexName);
  val addSuggestionQuery: AddSuggestionQuery = new AddSuggestionQuery(indexName, suggestion)
  val indexCreationQuery: CreateCompletionsFieldQuery = new CreateCompletionsFieldQuery(indexName)

  val futureResponse: Future[Response] = for {
    responseOne <- EsClient.execute(indexExistsQuery)
    responseTwo <- EsClient.execute(indexCreationQuery) if (indexExistsQuery.getBooleanResult(indexExistsQuery.getResult(responseOne)))
    responseThree <- EsClient.execute(addSuggestionQuery)
  } yield responseThree

  futureResponse.map { response =>
  Ok("Feed title: " + (response.json))
}

2 个答案:

答案 0 :(得分:3)

我创建了一些伪代码:

checkIndexExists() map {
  case true => Future.successful()
  case false => createIndex()
} flatMap { _ =>
  query()
}.map { response =>
  Ok("Feed title: " + (response.json))
}.recover { 
  case _ => Ok("bla") 
} 

首先,如果索引存在,则启动查询。 然后,如果成功,您将映射未来如何使用Future[Boolean]。由于您使用地图,因此您可以提取Boolean。如果索引存在,则只需创建已完成的未来。如果索引不存在,则需要启动索引创建命令。现在您遇到了嵌套FutureFuture[Future[Response]])的情况。使用flatMap删除一个维度,以便只有Future[Response]。这可以映射到播放结果。

更新(MeiSign的实施):

  EsClient.execute(indexExistsQuery) map { response =>
      if (indexExistsQuery.getBooleanResult(indexExistsQuery.getResult(response))) Future.successful(Response)
      else EsClient.execute(indexCreationQuery)
    } flatMap { _ =>
      EsClient.execute(addSuggestionQuery)
    } map { response: Response =>
      Ok("Feed title: " + (response.json))
    }

答案 1 :(得分:0)

我找到了这个解决方案,但我不认为这是一个很好的解决方案因为Iam使用Await.result()这是一个阻塞操作。 如果有人知道如何在不阻止操作的情况下重构此代码,请告诉我。

def addSuggestion(indexName: String, suggestion: String) = Action.async {
  val indexExistsQuery: IndexExistsQuery = new IndexExistsQuery(indexName);
  val addSuggestionQuery: AddSuggestionQuery = new AddSuggestionQuery(indexName, suggestion)
  val indexCreationQuery: CreateCompletionsFieldQuery = new CreateCompletionsFieldQuery(indexName)

  val indexExists: Boolean = indexExistsQuery.getBooleanResult(indexExistsQuery.getResult(Await.result(EsClient.execute(indexExistsQuery), 5.second)))
  if (indexExists) {
    EsClient.execute(addSuggestionQuery).map { response => Ok("Feed title: " + (response.json)) }
  } else {
    val futureResponse: Future[Response] = for {
      responseTwo <- EsClient.execute(indexCreationQuery)
      responseThree <- EsClient.execute(addSuggestionQuery)
    } yield responseThree

    futureResponse.map { response =>
      {
        Ok("Feed title: " + (response.json))
      }
    }.recover { case _ => Ok("bla") }
  }
}