Scala: List[Future] to Future[List] 忽略失败的期货 [英] Scala: List[Future] to Future[List] disregarding failed futures

查看:37
本文介绍了Scala: List[Future] to Future[List] 忽略失败的期货的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种将任意长度的 Futures 列表转换为 Future of List 的方法.我正在使用 Playframework,所以最终,我真正想要的是 Future[Result],但为了让事情更简单,我们就说 Future[List[Int]]执行此操作的正常方法是使用 Future.sequence(...) 但有一个转折...我给出的列表通常有大约 10-20 个期货,它是这些期货之一失败的情况并不少见(它们正在发出外部 Web 服务请求).如果其中一个失败,我不必重试所有这些,我希望能够找到成功的那些并返回它们.

I'm looking for a way to convert an arbitrary length list of Futures to a Future of List. I'm using Playframework, so ultimately, what I really want is a Future[Result], but to make things simpler, let's just say Future[List[Int]] The normal way to do this would be to use Future.sequence(...) but there's a twist... The list I'm given usually has around 10-20 futures in it, and it's not uncommon for one of those futures to fail (they are making external web service requests). Instead of having to retry all of them in the event that one of them fails, I'd like to be able to get at the ones that succeeded and return those.

例如,执行以下操作不起作用

For example, doing the following doesn't work

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.

Instead of getting the only the exception, I'd like to be able to pull the 1 and 3 out of there. I tried using Future.fold, but that apparently just calls Future.sequence behind the scenes.

预先感谢您的帮助!

推荐答案

诀窍是首先确保没有任何期货失败..recover 是你的朋友,你可以把它和 map 结合起来,把所有的 Future[T] 结果转换成 Future[Try[T]]] 实例,所有这些都肯定是成功的未来.

The trick is to first make sure that none of the futures has failed. .recover is your friend here, you can combine it with map to convert all the Future[T] results to Future[Try[T]]] instances, all of which are certain to be successful futures.

注意:您也可以在此处使用 OptionEither,但是如果您特别想要,Try 是最干净的方法捕获异常

note: You can use Option or Either as well here, but Try is the cleanest way if you specifically want to trap exceptions

def futureToFutureTry[T](f: Future[T]): Future[Try[T]] =
  f.map(Success(_)).recover { case x => Failure(x)}

val listOfFutures = ...
val listOfFutureTrys = listOfFutures.map(futureToFutureTry(_))

然后像之前一样使用Future.sequence,给你一个Future[List[Try[T]]]

Then use Future.sequence as before, to give you a Future[List[Try[T]]]

val futureListOfTrys = Future.sequence(listOfFutureTrys)

然后过滤:

val futureListOfSuccesses = futureListOfTrys.map(_.filter(_.isSuccess))

如果需要,您甚至可以提取特定的故障:

You can even pull out the specific failures, if you need them:

val futureListOfFailures = futureListOfTrys.map(_.filter(_.isFailure))

这篇关于Scala: List[Future] to Future[List] 忽略失败的期货的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆