En su lugar, podría usar una para la comprensión de la siguiente manera:
val fut1 = Future{...}
val fut2 = Future{...}
val fut3 = Future{...}
val aggFut = for{
f1Result <- fut1
f2Result <- fut2
f3Result <- fut3
} yield (f1Result, f2Result, f3Result)
En este ejemplo, los futuros 1, 2 y 3 se inician en paralelo. Luego, en el modo de comprensión, esperamos hasta que estén disponibles los resultados 1 y luego 2 y luego 3. Si falla 1 o 2, no esperaremos más a 3. Si los 3 tienen éxito, entonces aggFut
val mantendrá una tupla con 3 ranuras, correspondiente a los resultados de los 3 futuros.
Ahora, si necesita el comportamiento en el que desea dejar de esperar si dice que fut2 falla primero, las cosas se ponen un poco más complicadas. En el ejemplo anterior, tendría que esperar a que se complete fut1 antes de darse cuenta de que fut2 falló. Para resolver eso, puedes probar algo como esto:
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)
}
Ahora, esto funciona correctamente, pero el problema proviene de saber cuál Future
eliminar Map
cuando se ha completado correctamente. Siempre que tenga alguna forma de correlacionar adecuadamente un resultado con el Futuro que generó ese resultado, algo como esto funciona. Simplemente sigue eliminando de forma recursiva los futuros completados del mapa y luego llamando Future.firstCompletedOf
al resto Futures
hasta que no quede ninguno, recopilando los resultados a lo largo del camino. No es bonito, pero si realmente necesitas el comportamiento del que estás hablando, entonces esto o algo similar podría funcionar.