Estou procurando uma maneira de converter uma lista de comprimento arbitrário de Futuros em um Futuro de Lista. Estou usando o Playframework, então, no final das contas, o que eu realmente quero é um Future[Result]
, mas para tornar as coisas mais simples, vamos apenas dizer que Future[List[Int]]
a maneira normal de fazer isso seria usar, Future.sequence(...)
mas há uma reviravolta ... cerca de 10-20 futuros nele, e não é incomum que um desses futuros falhe (eles estão fazendo solicitações externas de serviço da web). Em vez de tentar novamente todos eles caso um deles falhe, eu gostaria de poder pegar aqueles que tiveram sucesso e devolvê-los.
Por exemplo, fazer o seguinte não funciona
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
Em vez de obter a única exceção, gostaria de poder extrair o 1 e o 3 de lá. Tentei usar Future.fold
, mas aparentemente só chama Future.sequence
nos bastidores.
Obrigado antecipadamente pela ajuda!
.recover
era de fato a peça que faltava para mim._.collect{ case Success(x) => x}
vez de_.filter(_.isSuccess)
se livrarTry
em tipo defutureListOfSuccesses
..recover(x => Failure(x))
não é válido, use em.recover({case e => Failure(e)})
vez dissoScala 2.12 tem uma melhoria em
Future.transform
que se presta a uma resposta com menos códigos.fonte
Tentei a resposta de Kevin e encontrei uma falha na minha versão do Scala (2.11.5) ... Corrigi isso e escrevi alguns testes adicionais se alguém estiver interessado ... aqui está a minha versão>
fonte
Acabei de me deparar com esta pergunta e tenho outra solução a oferecer:
A ideia aqui é que dentro da dobra você está esperando que o próximo elemento da lista seja concluído (usando a sintaxe para compreensão) e se o próximo falhar, você simplesmente volta para o que já tem.
fonte
Você pode facilmente agrupar resultados futuros com opção e, em seguida, nivelar a lista:
fonte
Você também pode coletar resultados bem-sucedidos e malsucedidos em listas diferentes:
fonte