Натомість ви можете використовувати для розуміння наступне:
val fut1 = Future{...}
val fut2 = Future{...}
val fut3 = Future{...}
val aggFut = for{
f1Result <- fut1
f2Result <- fut2
f3Result <- fut3
} yield (f1Result, f2Result, f3Result)
У цьому прикладі ф'ючерси 1, 2 і 3 стартують паралельно. Потім, для розуміння, ми чекаємо, поки будуть доступні результати 1, а потім 2, а потім 3. Якщо 1 або 2 не вдасться, ми більше не будемо чекати 3. Якщо всі 3 досягнуть успіху, тоді aggFut
вал буде містити кортеж з 3 слотами, що відповідає результатам 3 ф'ючерсів.
Тепер, якщо вам потрібна поведінка, коли ви хочете перестати чекати, якщо скажімо, що спочатку не виходить fut2, все стає трохи складніше. У наведеному вище прикладі вам доведеться почекати завершення fut1, перш ніж зрозуміти, що fut2 не вдалося. Щоб вирішити це, ви можете спробувати щось подібне:
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)
}
Зараз це працює правильно, але проблема виникає в тому, що ми знаємо, що Future
видалити з того, Map
коли один буде успішно завершено. Поки у вас є якийсь спосіб правильно співвіднести результат із майбутнім, яке породило цей результат, тоді щось подібне працює. Він просто рекурсивно продовжує видаляти завершені ф’ючерси з карти, а потім закликати Future.firstCompletedOf
решту, Futures
поки не залишиться жодного, збираючи результати по дорозі. Це не красиво, але якщо вам дійсно потрібна поведінка, про яку ви говорите, тоді це або щось подібне може спрацювати.