Vous pouvez utiliser un for-compréhension comme suit à la place:
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 futurs 1, 2 et 3 sont lancés en parallèle. Ensuite, dans la pour la compréhension, nous attendons que les résultats 1 puis 2 puis 3 soient disponibles. Si 1 ou 2 échoue, nous n'attendrons 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, disons, fut2 échoue en premier, les choses deviennent un peu plus délicates. Dans l'exemple ci-dessus, vous devrez attendre que fut1 se termine avant de réaliser l'échec de fut2. Pour résoudre ce problème, vous pouvez 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 lequel Future
supprimer de Map
celui qui a été terminé avec succès. Tant que vous avez un moyen de corréler correctement un résultat avec le futur qui a engendré ce résultat, alors quelque chose comme ça fonctionne. Il continue de supprimer récursivement les contrats à terme terminés de la carte, puis d'appeler Future.firstCompletedOf
les autres Futures
jusqu'à ce qu'il n'en reste plus, collectant les résultats en cours de route. Ce n'est pas joli, mais si vous avez vraiment besoin du comportement dont vous parlez, alors ceci ou quelque chose de similaire pourrait fonctionner.