List[Future[A]] => Future[(List[A], List[Throwable])] 最正确的解决方案

问题描述 投票:0回答:1

我有解决方案:

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))

有什么问题吗,或者有更正确的解决办法吗

list scala future
1个回答
0
投票

正如评论中提到的,我要强调两件事:

  1. 风格:使用直接

    _1
    _2
    访问器时,元组可能会变得难以阅读,一般来说,我认为解构并给每个字段命名是一个很好的做法(有时可能会考虑

  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 上使用此代码

© www.soinside.com 2019 - 2024. All rights reserved.