5

我有 3 个响应类型的期货。第一个future返回一个JsValue,它定义是执行future 2和future 3还是只执行future 3。

伪代码:如果 Future 1 那么 {future2 and future 3} else future 3

我试图在一个游戏框架动作中做到这一点,这意味着为了以后使用期货的结果,我不能使用 onSuccess、onFailure 和 onComplete,因为它们都返回 Unit 而不是上一个未来的实际 JsValue。

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

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))
}
4

2 回答 2

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. 如果索引存在,您只需创建一个已经完成的未来。如果索引不存在,您需要启动索引创建命令。现在您遇到了嵌套Future's ( Future[Future[Response]]) 的情况。使用flatMap您删除一个维度,因此您只有Future[Response]. 这可以映射到 Play 结果。

更新(美信的实现):

  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))
    }
于 2013-10-23T20:55:14.120 回答
0

我找到了这个解决方案,但我认为这不是一个好的解决方案,因为我正在使用 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") }
  }
}
于 2013-10-23T20:52:23.933 回答