Ответ 1
По-настоящему полезная вещь (вообще говоря) должна была бы способствовать тому, чтобы ошибка будущего в правильное значение. Другими словами, преобразуйте a Future[T]
в Future[Try[T]]
(успешное возвращаемое значение становится 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 )
Вы получите успешный 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 } )
}