Scala、Play和Futures:如何从多个Futures中合并结果

11

我正在使用:

  • Scala 2.10
  • Play 2.1

目前,我正在使用scala.concurrent._中的Future类,但我愿意尝试其他API。

我遇到了将多个futures的结果合并成单个List [(String,String)]的问题。

以下Controller方法成功地将单个Future的结果返回到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)]())))
          }
        }
      })
  }

The method getSearchResult(String, Int)执行Web服务API调用并返回Future [play.api.libs.ws.Response]。方法getAuthors(String, List [(String, String)])将返回一个List [(String, String)]到HTML模板中。
现在,我正在尝试在for循环中调用getSearchResult(String, Int)以获取多个响应体。以下内容应该可以说明我的意图,但我得到了一个编译时错误:
  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)]]],需要:List [(String,String)]。
我如何将多个Future对象的响应映射到单个Result?
1个回答

11
创建一个由结果类型的列表或其他集合参数化的未来。
此处
在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)

嗯,那个链接有帮助。我尝试了Julian Richard-Foy发布的方法:val httpResponses = Promise.sequence(List(remoteCall1, remoteCall2))。这让我得到了一个Future[IndexedSeq[Response]]实例,非常棒。然而,我仍在努力将响应列表映射为单个[(String, String)]列表。现在,它只映射第一个Future的结果。 - David Kaczynski
@DavidKaczynski 在我的 Java 应用程序中,我们编写了一个小的 Promise 库并创建了一个 Promise.whenAll(Promise...) 方法。因此,在研究您的问题时,我尝试通过 Google 搜索 "scala play promise from collection," "...from list" 等内容。我真的希望这样的方法非常标准化。另请参见:https://github.com/playframework/Play20/pull/677 - djechlin
经过进一步检查,我在第一条评论中描述的方法有效。我还有另一个“错误”,只返回一个future的结果。一旦我从不同的Futures序列创建了Promise,我就可以在单个Future中获取所有响应。太棒了! - David Kaczynski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接