Play 2.2 -Scala - 如何在控制器动作中链接期货 [英] Play 2.2 -Scala - How to chain Futures in Controller Action

查看:18
本文介绍了Play 2.2 -Scala - 如何在控制器动作中链接期货的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have 3 futures of type Response. The first future returns a JsValue which defines if future 2 and future 3 shall be executed or only future 3 shall be executed.

伪代码:如果 Future 1 那么 {future2 and future 3}否则未来3

Pseudocode: If Future 1 then {future2 and future 3} else future 3

我正在尝试在 play 框架操作中执行此操作,这意味着为了以后使用期货的结果,我不能使用 onSuccess、onFailure 和 onComplete,因为它们都返回 Unit 而不是上次期货的实际 JsValue.

Iam trying to do this in a play framwork action which means in order to use the result of the futures later I cant use onSuccess, onFailure and onComplete because all of them return Unit and not the actual JsValue from the last future.

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

I tried to do this with map() and andThen but I am a Scala noob and I guess i wasn't able to do it because I always just missed a little point. Here is my current approach which does not work!

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

推荐答案

我创建了一些伪代码:

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 的 (Future[Future[Response]]).使用 flatMap 删除一维,这样你就只有 Future[Response].这可以映射到播放结果.

First you fire up the query if the index exists. Then you map that future how to work with that Future[Boolean] if it successful. Since you use map, you kind of extract the Boolean. If the index exists, you just create a future that is already complete. If the index not exists you need to fire up the index creation command. Now you have the situation that you have nested Future's (Future[Future[Response]]). Using flatMap you remove one dimension, so that you only have Future[Response]. That can be mapped to a Play result.

更新(MeiSign的实现):

Update (the implementation of 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))
    }

这篇关于Play 2.2 -Scala - 如何在控制器动作中链接期货的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆