scala, play, futures: combining results from multiple futures

asynchronous, future, playframework, playframework-2.1, scala

Solution

Create a Future parametrized by a List or other Collection of the Result type.

From here:

In Play 1 you can do this:

    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 less direct:

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

Problem

I am using: - Scala 2.10 - Play 2.1 Currently, I am using the `Future` class from `scala.concurrent._`, but I'm open to trying another API. I am having trouble combining the results of multiple futures into a single List[(String, String)]. The following `Controller` method successfully returns the results of a single Future to an HTML template: ``` 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)]()))) } } }) } ``` The method `getSearchResult(String, Int)` performs a web service API call and returns a Future[play.api.libs.ws.Response]. The method `getAuthors(String, List[(String, String)])` returns a List[(String, String)] to the HTML template. Now, I am trying to call `getSearchResult(String, Int)` in a `for` loop to get several Response bodies. The following should give an idea of what I'm trying to do, but I get a compile-time error: ``` 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)) } }) } ``` type mismatch; found : scala.collection.immutable.IndexedSeq[scala.concurrent.Future[List[(String, String)]]] required: List[(String, String)] How can I map the responses of several `Future` objects to a single `Result`?

Original source