2013-02-24 12 views
10

używam:scala, zabawy, kontrakty: łączenie wyników z wieloma kontraktami

  • Scala 2.10
  • Zagraj 2,1

Obecnie używam klasy Future z scala.concurrent._, ale Jestem otwarty na wypróbowanie innego API.

Mam problem z łączeniem wyników wielu kontraktów futures w jedną listę [(String, String)].

Poniższy Controller metoda skutecznie zwraca wyniki pojedynczego przyszłości do szablonu HTML:

def test = Action { implicit request => 
    queryForm.bindFromRequest.fold(
     formWithErrors => Ok("Error!"), 
     query => { 
     Async { 
      getSearchResponse(query, 0).map { response => 
      Ok(views.html.form(queryForm, 
       getAuthors(response.body, List[(String, String)]()))) 
      } 
     } 
     }) 
    } 

Sposób getSearchResult(String, Int) wykonuje wywołanie API usług internetowych i zwraca przyszłości [play.api.libs.ws .Odpowiedź]. Metoda getAuthors(String, List[(String, String)]) zwraca List [(String, String)] do szablonu HTML.

Teraz próbuję wywołać getSearchResult(String, Int) w pętli for, aby uzyskać kilka ciał odpowiedzi. Poniższy powinien dać wyobrażenie o tym, co staram się robić, ale pojawia się błąd kompilacji:

def test = Action { implicit request => 
    queryForm.bindFromRequest.fold(
     formWithErrors => Ok("Error!"), 
     query => { 
     Async { 
      val authors = for (i <- 0 to 100; if i % 10 == 0) yield { 
      getSearchResponse(query, i) 
      }.map { response => 
      getAuthors(response.body, List[(String, String)]()) 
      } 

      Ok(views.html.form(queryForm, authors)) 
     } 
     }) 
    } 

niezgodność typów; znaleziono: scala.collection.immutable.IndexedSeq [scala.concurrent.Future [List [(String, String)]]] wymagane: Lista [(String, String)]

Jak mogę zmapować odpowiedzi z kilku Future obiektów do pojedynczego Result?

Odpowiedz

9

Utwórz przyszłe parametry sparametryzowane przez listę lub inną kolekcję typu Wynik.

Od here:

In Play 1 można to zrobić:

F.Promise<List<WS.HttpResponse>> promises = F.Promise.waitAll(remoteCall1, remoteCall2, remoteCall3); 

    // where remoteCall1..3 are promises 

    List<WS.HttpResponse> httpResponses = await(promises); // request gets suspended here 

In Play 2 mniej Direct:

val httpResponses = for { 
    result1 <- remoteCall1 
    result2 <- remoteCall2 
} yield List(result1, result2) 
+0

Hm, linkujące pomaga. Próbowałem podejścia opublikowanego przez Juliana Richarda-Foy: 'val httpResponse = Promise.sequence (List (remoteCall1, remoteCall2))'. To pozwoliło mi uzyskać instancję 'Future [IndexedSeq [Response]]', która jest niesamowita. Jednak nadal próbuję zmapować listę odpowiedzi na pojedynczą listę [(String, String)]. Teraz tylko mapuje wynik pierwszego Future –

+0

@DavidKaczynski W mojej aplikacji Java skończyliśmy pisać małą bibliotekę Promise i stworzyliśmy metodę "Promise.whenAll (Promise ...)". Tak więc w badaniu twojego pytania próbowałem Googling w takich rzeczach jak "scala play promise from collection", "... from list," itd. Takiej metody naprawdę bym się spodziewał być bardzo standardowym. Zobacz także: https://github.com/playframework/Play20/pull/677 – djechlin

+0

Po dokładnej inspekcji zadziałała metoda opisana w moim pierwszym komentarzu. Miałem kolejny "błąd", który zwracał wyniki tylko z jednej przyszłości. Kiedy stworzyłem Promise z sekwencji ** różnych ** Futures, otrzymywałem wszystkie odpowiedzi w jednej Przyszłości. Niesamowite rzeczy! –

Powiązane problemy