如何结合 Scala Play2 中多个响应的数据?

How combine data from several responses in Scala Play2?

我需要对不同的 URL 做一些请求,从他们的响应中获取数据并将这些信息放在一个列表中,但我对这个主题有一些误解。 1) 对于一个请求,我做了

def doRequest: Future[WSResponse] = {
client
  .url("MY_URL")
  .withRequestTimeout(5000)
  .get()}

然后我解析 json 以响应我的对象列表:

def list: Future[List[FoobarEntry]] = {
doRequest.map {
  response => {
    val json = response.json \ "foobar"
      json.validate[List[FoobarEntry]] match {
      case js:JsSuccess[List[FoobarEntry]]=>
        js.get
      case e:JsError => Logger.error(JsError.toFlatJson(e).toString()); List()
    }
  }
}}

我认为对于几个 url 我应该写一些看起来像

def doRequests: List[Future[WSResponse]] = {
List(client
     .url("URL_1")
     .withRequestTimeout(5000)
     .get(),
     client
     .url("URL_2")
     .withRequestTimeout(5000)
     .get())}

但是如何像我的 def list: Future[List[FoobarEntry]] 一样解析这个 Future[WSResponse] 列表?

由于您将未来的响应放在列表中,因此您必须将每个未来的响应映射到将其转换为 FoobarEntry 的解析逻辑。像这样:

val responseFutures: List[Future[WSResponse]] = ???
val foobarFutures: List[Future[FoobarEntry]] = 
  responseFutures.map(future => future.map(response => parse(response)))

现在您有了一个未来已解析响应的列表,但是要在所有响应都到达时执行某些操作,您需要对该列表进行排序:

val futureFoobars = Future.sequence(foobarFutures)

因此,顺序可以帮助您从 C[Future[A]]Future[C[A]]

使用 for-comprehensions。

val request1 = client.url("URL_1").withRequestTimeout(5000).get()   
val request2 = client.url("URL_2").withRequestTimeout(5000).get() 
val result: Future[List[FoobarEntry]] = for {
   res1: WSResponse <- request1
   res2: WSResponse <- request2
} yield List(res1, res2).map(parse).flatten

def parse(response: WSResponse): List[FoobarEntry] = {
   val json = response.json \ "foobar"
   json.validate[List[FoobarEntry]] match {
      case js:JsSuccess[List[FoobarEntry]]=>
        js.get
      case e:JsError => Logger.error(JsError.toFlatJson(e).toString()) 
        List()
    }