我有解决方案:
def foo[A](futures: List[Future[A]])(implicit ec: ExecutionContext): Future[(List[A], List[Throwable])] =
futures.foldLeft(Future.successful(List.empty[A] -> List.empty[Throwable] )) ( (acc, el) =>
acc.flatMap(a =>
el.map(f => (f :: a._1, a._2)).recover{
case NonFatal(e) => (a._1 , e :: a._2)
}
)
).map(f => (f._1.reverse, f._2.reverse))
有什么问题吗,或者有更正确的解决办法吗
正如评论中提到的,我要强调两件事:
风格:使用直接
_1
、_2
访问器时,元组可能会变得难以阅读,一般来说,我认为解构并给每个字段命名是一个很好的做法(有时可能会考虑
性能:虽然很小,但避免做不必要的工作仍然很好。正如评论中提到的,如果您想附加,您可能应该看看使用具有恒定时间附加的集合。由于显然您需要返回
List
,因此您可以通过使用 reverse
来避免 foldRight
ing:
def foo[A](
futures: Seq[Future[A]]
)(implicit ec: ExecutionContext): Future[(List[A], List[Throwable])] =
futures
.foldRight(Future.successful((List.empty[A], List.empty[Throwable])))(
(el, acc) =>
acc.flatMap { case (oks, errs) =>
el.map(ok => (ok :: oks, errs)).recover { case NonFatal(err) =>
(oks, err :: errs)
}
}
)
您可以在 Scastie 上使用此代码。