Szukam sposobu na przekonwertowanie dowolnej długości listy kontraktów futures na przyszłość listy. Używam Playframework, więc ostatecznie naprawdę chcę Future[Result]
, ale żeby wszystko było prostsze, powiedzmy, że Future[List[Int]]
Normalnym sposobem byłoby użycie, Future.sequence(...)
ale jest pewien zwrot akcji ... Lista, którą otrzymuję, zwykle ma około 10-20 kontraktów futures i nierzadko zdarza się, że jedna z nich zawodzi (wykonują zewnętrzne żądania usług internetowych). Zamiast ponawiać próby wszystkich z nich w przypadku, gdy jeden z nich zawiedzie, chciałbym mieć możliwość uzyskania dostępu do tych, którym się powiodło, i zwrócenia tych.
Na przykład wykonanie poniższych czynności nie działa
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
Zamiast otrzymywać jedyny wyjątek, chciałbym móc wyciągnąć stamtąd 1 i 3. Próbowałem użyć Future.fold
, ale to najwyraźniej tylko dzwoni Future.sequence
za kulisami.
Z góry dziękuję za pomoc!
.recover
był rzeczywiście brakującym elementem dla mnie._.collect{ case Success(x) => x}
zamiast,_.filter(_.isSuccess)
aby pozbyć sięTry
typufutureListOfSuccesses
..recover(x => Failure(x))
nie jest ważna, użyj.recover({case e => Failure(e)})
zamiast tegoScala 2.12 ma ulepszenie,
Future.transform
które nadaje się do odpowiedzi z mniejszą liczbą kodów.źródło
Wypróbowałem odpowiedź Kevina i napotkałem usterkę w mojej wersji Scali (2.11.5) ... Poprawiłem to i napisałem kilka dodatkowych testów, jeśli ktoś jest zainteresowany ... oto moja wersja>
źródło
Właśnie natknąłem się na to pytanie i mam inne rozwiązanie do zaoferowania:
Pomysł polega na tym, że w folderze czekasz na zakończenie następnego elementu na liście (używając składni for-compension), a jeśli następny zawiedzie, po prostu wracasz do tego, co już masz.
źródło
Możesz łatwo zawinąć przyszły wynik opcją, a następnie spłaszczyć listę:
źródło
Możesz również zbierać udane i nieudane wyniki na różnych listach:
źródło