2013-10-23 22 views
4

我有3類期貨的迴應。第一個未來將返回一個JsValue,它定義將來2和將來3將被執行還是僅僅執行未來3。玩2.2 -Scala - 如何在控制器行動鏈期貨

僞代碼: 如果未來1,則{future2和未來3} 否則未來3

蔭試圖做到這一點的一齣戲framwork行動,這意味着爲了以後使用期貨的結果,我不能使用onSuccess,onFailure和onComplete,因爲它們都返回Unit而不是最後一個未來的實際JsValue。

我試圖用map()和then來做到這一點,但我是斯卡拉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)) 
} 

回答

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

這裏實施的解決方案,非常感謝你: https://gist.github.com/MeiSign/d7ab401c717e8b8ef6b9 – MeiSign

+1

你爲什麼要創建索引@運行?不應該這樣做嗎? –

+1

在我的用例索引中有一個固定的映射,我希望能夠在運行時創建它們。我們在這裏談論的是可被視爲內容容器的elasticsearch索引。 – MeiSign

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