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

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

问题描述

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

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

我正在尝试通过播放框架动作来执行此操作,这意味着为了以后使用期货的结果,我不能使用onSuccess,onFailure和onComplete,因为它们全部返回Unit,而不是最后一个期货的实际JsValue. /p>

我试图用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))
}

解决方案

我创建了一些伪代码:

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].可以将其映射到播放结果.

更新(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))
    }

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.

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

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.

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

解决方案

I created some pseudocode:

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

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.

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

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

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