首页 文章

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

提问于
浏览
5

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

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

我试图在一个游戏框架动作中这样做,这意味着为了使用后期的结果我不能使用onSuccess,onFailure和onComplete,因为所有这些都返回Unit而不是最后一个实际的JsValue .

我尝试用map()和andThen做这个,但我是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

    我创建了一些伪代码:

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

    首先,如果索引存在,则启动查询 . 然后,如果成功,您将映射未来如何使用 Future[Boolean] . 由于你使用map,你可以提取 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))
        }
    
  • 3

    我找到了这个解决方案,但我不认为这是一个很好的解决方案,因为我使用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") }
      }
    }
    

相关问题