Вместо этого вы можете использовать для понимания следующим образом:
val fut1 = Future{...}
val fut2 = Future{...}
val fut3 = Future{...}
val aggFut = for{
f1Result <- fut1
f2Result <- fut2
f3Result <- fut3
} yield (f1Result, f2Result, f3Result)
В этом примере фьючерсы 1, 2 и 3 запускаются параллельно. Затем, для понимания, мы ждем, пока не станут доступны результаты 1, затем 2 и 3. Если 1 или 2 выйдет из строя, мы больше не будем ждать 3. Если все 3 успешны, то aggFut
val будет содержать кортеж с 3 слотами, соответствующий результатам 3 фьючерсов.
Теперь, если вам нужно поведение, при котором вы хотите перестать ждать, если, скажем, сначала выйдет из строя fut2, все становится немного сложнее. В приведенном выше примере вам придется подождать завершения работы fut1, прежде чем вы поймете, что fut2 не удалось. Чтобы решить эту проблему, вы можете попробовать что-то вроде этого:
val fut1 = Future{Thread.sleep(3000);1}
val fut2 = Promise.failed(new RuntimeException("boo")).future
val fut3 = Future{Thread.sleep(1000);3}
def processFutures(futures:Map[Int,Future[Int]], values:List[Any], prom:Promise[List[Any]]):Future[List[Any]] = {
val fut = if (futures.size == 1) futures.head._2
else Future.firstCompletedOf(futures.values)
fut onComplete{
case Success(value) if (futures.size == 1)=>
prom.success(value :: values)
case Success(value) =>
processFutures(futures - value, value :: values, prom)
case Failure(ex) => prom.failure(ex)
}
prom.future
}
val aggFut = processFutures(Map(1 -> fut1, 2 -> fut2, 3 -> fut3), List(), Promise[List[Any]]())
aggFut onComplete{
case value => println(value)
}
Теперь это работает правильно, но проблема возникает из-за того, что Future
нужно знать, что удалить из того, Map
когда один был успешно завершен. Если у вас есть способ правильно соотнести результат с Будущим, породившим этот результат, что-то вроде этого работает. Он просто рекурсивно удаляет завершенные фьючерсы с карты, а затем вызывает Future.firstCompletedOf
оставшиеся Futures
до тех пор, пока не останется ни одного, собирая результаты по пути. Это некрасиво, но если вам действительно нужно поведение, о котором вы говорите, то это или что-то подобное может сработать.