2013-05-13 28 views
1

我GOOGLE了這一點,無法找到答案。做異步GET就像一個循環,但等待每個響應

我想要在Scala/play框架中創建一個URL,然後對結果進行一些操作。如果結果包含我想要的,那麼我想用其他參數再次調用它。這可能會達到100次,所以我無法嵌套幾個WS。我希望像一個循環一遍又一遍地做同樣的調用,直到我找到我要找的東西,但是當我把下面的所有代碼都封裝在一個循環中時,它不會等待每個調用完成,我明白了。但我該如何解決這個問題?

var index = 0 

val call = WS.url("http://urlToGetSomethingFrom&parameter="+index).get() 

for{ 

response <- call 

} yield{ 

    val something: String = response.json/"name" 

    if(something.equals("Eric")){ 

    //I'm finished, break out 

    }else{ 

    index += 1 

    //and then I want to do the same call again 
    } 

} 

回答

0

get()返回Future
爲了等待它完成,您需要將它傳遞到Await.result以及到期持續時間。

這裏舉例:https://stackoverflow.com/a/16296848/604041

+0

因爲你是第一個與工作的例子我要去將其標記爲正確的答案。謝謝 – korrekorre 2013-05-15 08:45:59

+0

謝謝。 - @投票給我答案的人:你至少可以解釋爲什麼。 – 2013-05-15 14:37:35

0

下面是不使用阻塞的解決方案。 關鍵是它使用遞歸調用,它使用flatMap並返回Promise.pure以獲得所需的結果。

因爲它是一個使用舊的google搜索api的實際工作示例,所以它更復雜一點,因爲有一個列表/ Seq的映射和檢查謂詞函數。

package controllers 

import play.api._ 
import play.api.mvc._ 
import play.api.libs.concurrent.Promise 
import play.api.libs.json._ 
import play.api.libs.ws.WS 
import scala.concurrent.Future 
import scala.concurrent.ExecutionContext.Implicits.global 

object Application extends Controller { 

    def index = Action { 

    def callWS(index: Int, f: String => Boolean): Future[String] = { 
     WS.url("https://ajax.googleapis.com/ajax/services/search/web") 
     .withQueryString(("v", "1.0"), ("q", "foo" + index)).get 
     .flatMap { response => 
      val titles = (response.json \ "responseData" \ "results" \\ "title") 
      titles.map(_.as[String]).find(f(_)).map(Promise.pure(_)).getOrElse(callWS(index + 1, f)) 
     } 
    } 

    Async(callWS(0, _.contains("FOO-1")).map(Ok(_))) 
    } 

} 
+0

這是有目標的,非阻塞的。將看看它!謝謝 – korrekorre 2013-05-15 08:47:00

+0

順便說一句,我看到這個/我的方法的一個問題是,遞歸使用堆棧(顯然不是尾遞歸),因此並不真正縮放。對於s.th.就像100個「循環」一樣,這不會是一個問題(如果你沒有顯着降低堆棧幀大小/ -Xss),但它會在某個時間點運行到StackOverflowError ... – MartinGrotzke 2013-05-15 09:17:16

+0

您可以交換堆棧堆使用蹦牀。見例如http://apocalisp.wordpress.com/2011/10/26/tail-call-elimination-in-scala-monads/ – 2013-05-15 10:58:54

1

我認爲這與@ MartinGotzke的答案基本相同。我實際上沒有試圖編譯這個或任何東西,但希望它可以幫助...祝你好運!

/** Keep looking until you find Eric */ 
    def findEric(index:Int):Future[Response] = { 
     WS.url("http://urlToGetSomethingFrom&parameter="+index).get(
     ).flatMap( 
      (resp) => if(resp.json/"name" == "Eric") Promise.successful(resp).future 
        else findEric(index+1) 
     ) 
    } 


    findEric(0).onComplete((resp) => { /* whatever it is you really want to do */ }) 
+0

您可以將'Promise.successful(x).future '用'Future.successful(x)' – 2013-05-15 10:56:53