【问题标题】:What's the right way to convert from a IndexedSeq[Future[Foo]] to a Future[IndexedSeq[Foo]]?从 IndexedSeq[Future[Foo]] 转换为 Future[IndexedSeq[Foo]] 的正确方法是什么?
【发布时间】:2014-05-22 01:48:35
【问题描述】:

根据标题,给定一个IndexedSeq[Future[Foo]],我想生成一个在原始IndexedSeq 的所有未来都完成时完成的未来。最好的方法是什么?如果列表中有 Future.sequence 之类的东西,有没有一种很好的方法来链接调用?

考虑两种情况:

bar.createFuture(blah)     // Future[A]
  .flatMap(f1)             // f1: A -> Future[B]
  .flatMap(f2)             // f2: B -> Future[C]
  .map(f3)                 // f3: C -> IndexedSeq[Future[D]],
                           //   but would like to call flatMap(f3...???)

bar.createIndexedSeq(blah) // IndexedSeq[A]
  .map(f1)                 // f1: A -> B
  .map(f2)                 // f2: B -> C
  .map(f3)                 // f3: C -> Future[D]
  .???                     // convert IndexedSeq[Future[D]]
                           //   into Future[IndexedSeq[D]]
  .map(f4)                 // f4: IndexedSeq[D] -> E

【问题讨论】:

  • 这不会为 Reactive Beauty 赢得价格,但我经常做的是为每个未来创建一个计数的 CountDownLatch。当每个未来完成(好或坏)时,它会减少计数。

标签: scala


【解决方案1】:

Future.sequence 将从IndexedSeq[Future[Foo]] 转换为Future[IndexedSeq[Foo]],实际上它将任何期货集合转换为持有相同类型集合的期货。

你的第一个用例可以这样写:

for {
  x <- bar.createFuture(blah)
  y <- f1(x)
  z <- f2(y)
  w <- Future.sequence(f3(z))
} yield w

你的第二个可以这样写:

Future.sequence(bar.createIndexedSeq(blah) map f1 map f2 map f3) map f4

或者Future.traverse:

Future.traverse(bar.createIndexedSeq(blah) map f1 map f2)(f3) map f4

【讨论】:

  • 谢谢,难道没有某种收集器可以为上面的第二个示例完成这项工作吗?我试图使所有操作保持逻辑顺序。我实际上对提供给 Future.sequence 的隐式参数有问题(请参阅stackoverflow.com/questions/23796942/…)。
  • 我不确定您所说的收集器是什么意思,但示例中保留了逻辑顺序,除了 Future.traverse 在旁边。如果这让您感到困扰,您可以使用 vals 中的中间结果重写它,并将其分成任意多行。
猜你喜欢
  • 2013-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
  • 1970-01-01
  • 1970-01-01
  • 2019-10-25
相关资源
最近更新 更多