Scala, игра, фьючерсы: объединение результатов нескольких фьючерсов

Я использую:

  • Scala 2.10
  • Play 2.1

В настоящее время я использую класс Future из scala.concurrent._, но я открыт для использования другого API.

У меня возникли проблемы с объединением результатов нескольких фьючерсов в один Список [(String, String)].

Следующий метод Controller успешно возвращает результаты одного будущего в 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)]())))
          }
        }
      })
  }

Метод getSearchResult(String, Int) выполняет вызов API веб-службы и возвращает Future [play.api.libs.ws.Response]. Метод getAuthors(String, List[(String, String)]) возвращает List [(String, String)] в шаблон HTML.

Теперь я пытаюсь вызвать getSearchResult(String, Int) в цикле for, чтобы получить несколько тел Response. Следующее должно дать представление о том, что я пытаюсь сделать, но я получаю ошибку времени компиляции:

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

несоответствие типов; найдено: scala.collection.immutable.IndexedSeq [scala.concurrent.Future [List [(String, String)]]] required: List [(String, String)]

Как сопоставить ответы нескольких объектов Future с одним Result?

Ответ 1

Создать будущее, параметризованное списком или другой коллекцией типа результата.

Из здесь:

В Play 1 вы можете сделать это:

    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

В Play 2 меньше прямого:

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