À la place, vous pourriez utiliser un for-comprehension comme suit :
val fut1 = Future{...}
val fut2 = Future{...}
val fut3 = Future{...}
val aggFut = for{
f1Result <- fut1
f2Result <- fut2
f3Result <- fut3
} yield (f1Result, f2Result, f3Result)
Dans cet exemple, les futures 1, 2 et 3 sont lancées en parallèle. Ensuite, dans la compréhension du for, on attend que les résultats 1 puis 2 puis 3 soient disponibles. Si 1 ou 2 échoue, on n'attendra plus 3. Si les 3 réussissent, alors le aggFut
val contiendra un tuple avec 3 slots, correspondant aux résultats des 3 futures.
Maintenant, si vous avez besoin du comportement où vous voulez arrêter d'attendre si fut2 échoue d'abord, les choses deviennent un peu plus délicates. Dans l'exemple ci-dessus, vous devriez attendre que le fut1 se termine avant de réaliser que le fut2 a échoué. Pour résoudre ce problème, vous pourriez essayer quelque chose comme ceci :
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)
}
Maintenant, cela fonctionne correctement, mais le problème vient du fait de savoir quelle Future
à retirer de la Map
lorsque l'une d'entre elles a été menée à bien. Tant que vous avez un moyen de corréler correctement un résultat avec le Future qui a engendré ce résultat, alors quelque chose comme ça fonctionne. Il suffit de retirer récursivement de la carte les Futures terminés, puis d'appeler Future.firstCompletedOf
sur les autres Futures
jusqu'à ce qu'il n'y en ait plus, en recueillant les résultats en cours de route. Ce n'est pas très joli, mais si vous avez vraiment besoin du comportement dont vous parlez, alors ceci, ou quelque chose de similaire, pourrait fonctionner.