将 List[Future[Int]] 转换为具有失败期货的 Future[List[Int]]

Converting List[Future[Int]] to Future[List[Int]] with failed futures

假设我有以下片段

def testFailure2() = {
    val f1 = Future.failed(new Exception("ex1"))
    val f2 = Future.successful(2);
    val f3 = Future.successful((5));
    val f4 = Future.failed(new Exception("ex4"))
    val l = List(f1, f2, f3, f4)
    l
  }

return 类型是 List[Future[Int]]。在正常情况下,我可以只做 Future.sequence 并得到 List[Future[Int]]。但在这种情况下,它不会起作用,因为我的 Future 失败了。所以我想通过忽略失败的 Futures 将其转换为 List[Future[Int]]。我该怎么做?

我有关于类似主题的第二个问题,我理解 filter, collect, partition, etc on a List。在这种情况下,假设我想将 filter/partitionlist 分成两个列表 - 失败的期货合二为一 - 在另一个人中成功完成了 Futures。

我该怎么做?

一种方法是首先将所有 Future[Int] 转换为总是成功的 Future[Option[Int]](但如果原始 future 失败,则会导致 None)。然后你可以使用Future.sequence然后压平结果:

def sequenceIgnoringFailures[A](xs: List[Future[A]])(implicit ec: ExecutionContext): Future[List[A]] = {
  val opts = xs.map(_.map(Some(_)).fallbackTo(Future(None)))
  Future.sequence(opts).map(_.flatten)
}

另一个答案是正确的:您应该使用 Future[List[X]],其中 X 是区分失败和成功的东西。它可以是一个选项、一个选择、一个尝试或任何你想要的。

您似乎对此感到困扰,我想这是因为您愿意找到类似的东西:

  • 并行执行所有这些 futures,忽略过程中失败的那些

你得到了

  • 做所有这些期货,等待一切完成,并根据结果丢弃

但其实并没有什么特别的表达方式"ignore the failed ones"。因为你对它感兴趣,所以必须承认每一个未来的结果,否则一开始就没有意义。无论如何,这必须等待所有期货完成。因此,"you can now ignore me" 的标志确实是 None 的选项,左边的 Either 或失败的 Try。 "this result being discarded",afaik,没有特定的期货标志,我认为 scala 不需要一个。

所以,不要害怕,选择 Future[List[X]],因为它实际上表达了你想要的! :-)