scala - 在执行未来的序列失败时,如何进行?

  显示原文与译文双语对照的内容
0 0

traverse方法从 Future停在第一个对象失败。 我想通过一种tolerant/forgiving版本的该方法,在执行时出现的错误与剩余的序列。

当前我们添加下面的方法到我们的utils :

def traverseFilteringErrors[A, B <: AnyRef]
                           (seq: Seq[A])
                           (f: A => Future[B]): Future[Seq[B]] = {
  val sentinelValue = null.asInstanceOf[B]
  val allResults = Future.traverse(seq) { x =>
    f(x) recover { case _ => sentinelValue }
  }
  val successfulResults = allResults map { result =>
    result.filterNot(_ == sentinelValue)
  }
  successfulResults
}

有没有更好的方法?

时间:原作者:1个回答

0 0

一个真正有效方法( 一般来说) 中,以便能够升级自己的错误是一件以后转换为正确的值。 或者换句话说,转换 Future[T]转换为 Future[Try[T]]( succesful返回值将成为 Success[T]在故障情况下就变成了 Failure[T]) 。 我们可能会实现它的方法如下:

// Can also be done more concisely (but less efficiently) as:
// f.map(Success(_)).recover{ case t: Throwable => Failure( t ) }
// NOTE: you might also want to move this into an enrichment class
def mapValue[T]( f: Future[T] ): Future[Try[T]] = {
  val prom = Promise[Try[T]]()
  f onComplete prom.success
  prom.future
}

现在,如果你:

Future.traverse(seq)( f andThen mapValue )

你将获得一个succesful Future[Seq[Try[A]]]其最终值包含一个, Success实例为每个成功以后, Failure未来的每个实例失败。 如果需要,你可以使用 collect这个seq来围捕猎物上 Failure实例,只保留成功值函数。

换句话说,可以重新编写你的帮助器方法,如下所示:

def traverseFilteringErrors[A, B](seq: Seq[A])(f: A => Future[B]): Future[Seq[B]] = {
  Future.traverse( seq )( f andThen mapValue ) map ( _ collect{ case Success( x ) => x } )
}
原作者:
...