Scala:当其中一些超时时如何收集期货列表的结果?

Scala: How to gather the result of a list of futures when some of them time out?

我在这种情况下的做法是用.sequence把一个F[G[A]]变成一个G[F[A]]。然后用Await.result(future_of_a_list, time_out)得到结果。但是,可能有一项任务需要很长时间并超时。在这种情况下,我仍然想获得其余结果(同时 运行 所有任务并行进行)。可能吗?怎么做?

谢谢

好吧,您可以将每个 Await 包装在另一个 Future 中:

import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.util.Success

scala> val s = Seq(Future(1), Future(2), Future { Thread.sleep(2000); 3 })
s: Seq[scala.concurrent.Future[Int]] = List(Future(Success(1)), Future(Success(2)), Future(<not completed>))

scala> val fs = Future.traverse(s)(f => 
         Future(Await.result(f, 1 second)).transform(Success(_)))
fs: scala.concurrent.Future[Seq[scala.util.Try[Int]]] = Future(<not completed>)

scala> Await.result(fs, Duration.Inf)
res2: Seq[scala.util.Try[Int]] = List(Success(1), Success(2), Failure(java.util.concurrent.TimeoutException: Futures timed out after [1 second]))

我同意@Kolmar 的观点。只是他的解决方案中的 transform() 是新的 Scala 2.12.x 版本,而在 2.11.x 中它具有不同的签名。我尝试升级,但 运行 陷入依赖性问题。我找到了使用 2.11.x 的 fallbackTo 的方法。由于我的 Await.result(f, 1 second)) 将 return 变成 scalaz.Validation[Throwable, T],它也可以这样工作:

val fs = Future.traverse(s)(f => 
     Future(Await.result(f, 1 second)).fallbackTo(Future(Failure(new TimeoutException())))