Potresti invece usare una per la comprensione come segue:
val fut1 = Future{...}
val fut2 = Future{...}
val fut3 = Future{...}
val aggFut = for{
f1Result <- fut1
f2Result <- fut2
f3Result <- fut3
} yield (f1Result, f2Result, f3Result)
In questo esempio, i futures 1, 2 e 3 vengono avviati in parallelo. Quindi, nella fase di comprensione, aspettiamo che siano disponibili i risultati 1 e poi 2 e poi 3. Se 1 o 2 fallisce, non aspetteremo più 3. Se tutti e 3 hanno successo, aggFut
val conterrà una tupla con 3 slot, corrispondenti ai risultati dei 3 futures.
Ora, se hai bisogno del comportamento in cui vuoi smettere di aspettare se diciamo fut2 fallisce prima, le cose si fanno un po 'più complicate. Nell'esempio sopra, dovresti aspettare il completamento di fut1 prima di realizzare che fut2 non è riuscito. Per risolverlo, potresti provare qualcosa del genere:
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)
}
Ora funziona correttamente, ma il problema deriva dal sapere quale Future
rimuovere da Map
quando uno è stato completato con successo. Finché hai un modo per correlare correttamente un risultato con il futuro che ha generato quel risultato, allora qualcosa di simile funziona. Continua semplicemente a rimuovere in modo ricorsivo i Futures completati dalla mappa e quindi a chiamare Future.firstCompletedOf
i rimanenti Futures
finché non ne rimangono più, raccogliendo i risultati lungo il percorso. Non è carino, ma se hai davvero bisogno del comportamento di cui parli, allora questo o qualcosa di simile potrebbe funzionare.