Zamiast tego możesz użyć zrozumienia w następujący sposób:
val fut1 = Future{...}
val fut2 = Future{...}
val fut3 = Future{...}
val aggFut = for{
f1Result <- fut1
f2Result <- fut2
f3Result <- fut3
} yield (f1Result, f2Result, f3Result)
W tym przykładzie futures 1, 2 i 3 są uruchamiane równolegle. Następnie, w celu zrozumienia, czekamy, aż dostępne będą wyniki 1, a następnie 2 i 3. Jeśli 1 lub 2 zawiedzie, nie będziemy już czekać na 3. Jeśli wszystkie 3 się powiedzie, aggFut
val będzie trzymał krotkę z 3 miejscami, odpowiadającymi wynikom 3 futures.
Teraz, jeśli potrzebujesz zachowania, w którym chcesz przestać czekać, jeśli powiedz, że fut2 zawodzi jako pierwszy, sprawy stają się trochę trudniejsze. W powyższym przykładzie musisz poczekać, aż fut1 się zakończy, zanim zorientujesz się, że fut2 się nie powiodło. Aby rozwiązać ten problem, możesz spróbować czegoś takiego:
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)
}
Teraz działa to poprawnie, ale problem polega na tym, że wiemy, które Future
z nich usunąć z Map
pomyślnego ukończenia. Tak długo, jak masz jakiś sposób na poprawne skorelowanie wyniku z Przyszłością, która zrodziła ten wynik, wtedy coś takiego działa. Po prostu rekurencyjnie usuwa ukończone kontrakty futures z mapy, a następnie wywołuje Future.firstCompletedOf
pozostałe, Futures
dopóki ich nie ma, zbierając wyniki po drodze. To nie jest ładne, ale jeśli naprawdę potrzebujesz zachowania, o którym mówisz, to lub coś podobnego może zadziałać.