Я ищу способ преобразовать список Futures произвольной длины в Future of List. Я использую Playframework, поэтому в конечном итоге я действительно хочу Future[Result]
, но чтобы упростить задачу, скажем так Future[List[Int]]
. Обычный способ сделать это - использовать, Future.sequence(...)
но есть поворот ... В списке, который мне дают, обычно есть в нем около 10-20 фьючерсов, и нередко один из этих фьючерсов терпит неудачу (они делают запросы внешних веб-сервисов). Вместо того, чтобы повторять все из них в случае сбоя одного из них, я хотел бы иметь возможность получить те, которые были успешными, и вернуть их.
Например, следующее не работает
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.Success
import scala.util.Failure
val listOfFutures = Future.successful(1) :: Future.failed(new Exception("Failure")) ::
Future.successful(3) :: Nil
val futureOfList = Future.sequence(listOfFutures)
futureOfList onComplete {
case Success(x) => println("Success!!! " + x)
case Failure(ex) => println("Failed !!! " + ex)
}
scala> Failed !!! java.lang.Exception: Failure
Вместо того, чтобы получить единственное исключение, я хотел бы вытащить оттуда 1 и 3. Я пробовал использовать Future.fold
, но, видимо, это просто Future.sequence
закулисные звонки .
Заранее спасибо за помощь!
.recover
действительно был для меня недостающей частью._.collect{ case Success(x) => x}
вместо того,_.filter(_.isSuccess)
чтобы избавиться отTry
типаfutureListOfSuccesses
..recover(x => Failure(x))
недействительно, используйте.recover({case e => Failure(e)})
вместо негоВ Scala 2.12 есть улучшение,
Future.transform
которое заключается в ответе с меньшим количеством кодов.источник
Я попробовал ответить Кевина, и у меня возникла проблема с моей версией Scala (2.11.5) ... Я исправил это и написал несколько дополнительных тестов, если кому-то интересно ... вот моя версия>
источник
Я только что столкнулся с этим вопросом и могу предложить другое решение:
Идея здесь в том, что внутри свертки вы ждете завершения следующего элемента в списке (с использованием синтаксиса for-computing), а если следующий не работает, вы просто отключаетесь к тому, что у вас уже есть.
источник
Вы можете легко обернуть будущий результат с помощью option, а затем сгладить список:
источник
Вы также можете собирать успешные и неудачные результаты в разные списки:
источник