我有一个服务返回一个数据类型(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)
我将创建一个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]
。