Je cherche un moyen de convertir une liste de longueur arbitraire de Futures en Future of List. J'utilise Playframework, donc en fin de compte, ce que je veux vraiment, c'est un Future[Result]
, mais pour simplifier les choses, disons simplement que Future[List[Int]]
la façon normale de faire cela serait d'utiliser Future.sequence(...)
mais il y a une torsion ... La liste que l'on me donne a généralement environ 10-20 futurs, et il n'est pas rare que l'un de ces futurs échoue (ils font des demandes de service Web externes). Au lieu d'avoir à les réessayer tous au cas où l'un d'eux échouerait, j'aimerais pouvoir accéder à ceux qui ont réussi et les renvoyer.
Par exemple, faire ce qui suit ne fonctionne pas
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
Au lieu d'obtenir la seule exception, j'aimerais pouvoir retirer les 1 et 3 de là. J'ai essayé d'utiliser Future.fold
, mais cela n'appelle apparemment que Future.sequence
dans les coulisses.
Merci d'avance pour l'aide!
.recover
était en effet la pièce manquante pour moi._.collect{ case Success(x) => x}
au lieu de_.filter(_.isSuccess)
pour vous débarrasser de ceTry
type de fichierfutureListOfSuccesses
..recover(x => Failure(x))
n'est pas valide, utilisez à la.recover({case e => Failure(e)})
placeScala 2.12 a une amélioration
Future.transform
qui se prête à une réponse avec moins de codes.la source
J'ai essayé la réponse de Kevin, et j'ai rencontré un problème sur ma version de Scala (2.11.5) ... J'ai corrigé cela, et j'ai écrit quelques tests supplémentaires si quelqu'un est intéressé ... voici ma version>
la source
Je viens de tomber sur cette question et j'ai une autre solution à proposer:
L'idée ici est que dans le repli, vous attendez que l'élément suivant de la liste soit terminé (en utilisant la syntaxe pour la compréhension) et si le suivant échoue, vous revenez simplement à ce que vous avez déjà.
la source
Vous pouvez facilement encapsuler le résultat futur avec l'option, puis aplatir la liste:
la source
Vous pouvez également collecter les résultats réussis et non réussis dans différentes listes:
la source