使用一个服务调用(List)的结果来获取另一个List

jen*_*jen 6 scala

我有一个服务返回一个数据类型(Foo下面),其中包含一个id列表,用于getBar下面的第二个服务调用

case class Foo(barIds: List[Int])
case class Bar(id: Int)

val f = Future(List(Foo(List(1, 2)), Foo(List(5, 6))))
def getBar(l: List[Int]) = Future(l.map(Bar(_)))
Run Code Online (Sandbox Code Playgroud)

我需要的是 Future[List[Foo,List[Bar]]]

我先尝试了一个嵌套的for-understanding,但是

val rr = for {
    foos <- f
} yield  for {
    foo <- foos
    bars <- getBar(foo.barIds) // won't work as this is a Future and foos is a list
} yield (foo,bars)   
Run Code Online (Sandbox Code Playgroud)

然后我玩了一个映射游戏,(闻起来很可怕):

f.map(
    foos => foos.map(foo => (foo, foo.barIds)))
        .map(ts => ts.map(t => (t._1, getBar(t._2)))
)
Run Code Online (Sandbox Code Playgroud)

但这给了我一个 Future[List[Foo,Future[List[Bar]]]]

应该有一种方式来获得Future[List[Foo,List[Bar]]]并希望以更清洁的方式

这是一个scalafiddle https://scalafiddle.io/sf/P0FRIGs/0

请注意我之后的值是:带有Foo的元组和"他们"关联的Bar值列表:

List(
     (Foo(List(1, 2)),List(Bar(1), Bar(2))),
     (Foo(List(5, 6)),List(Bar(5), Bar(6)))
)
Run Code Online (Sandbox Code Playgroud)

Zol*_*tán 2

我将创建一个getBar返回传入参数的辅助包装方法foo,并将其与Future.traverse如下所示组合:

private def getFooAndBars(foo: Foo): Future[(Foo, List[Bar])] =
  getBar(foo.barIds).map(foo -> _)

val res: Future[List[(Foo, List[Bar])]] =
  f.flatMap(Future.traverse(_)(getFooAndBars))
Run Code Online (Sandbox Code Playgroud)

Future.traverse将获取每个foo,调用getFooAndBars它,然后展平列表,以便您得到 aFuture[List]而不是 a List[Future]