Как использовать transformWith(), чтобы игнорировать неудачные фьючерсы?

#scala #future

#scala #будущее

Вопрос:

Мне нужно обработать последовательность преобразований в одно преобразование, чтобы, если у меня есть какое-то неудачное будущее, его следует просто игнорировать (я пытаюсь сделать это без восстановления или восстановления с помощью, но что-то идет не так, код завершается сбоем при возникновении какого-либо сбоя)

 type Transformation[T] = T => Future[T]
//in - Seq(trans1, trans2, trans3)

in.reduce[Transformation[T]](
  (acc, el) =>
    acc.andThen[Future[T]](
      ft =>
        ft.flatMap(el)
          .transformWith[T](
            t =>
              t match {
                case Failure(exception) => ft //this line is the most suspicious for me
                case Success(value)     => Future.successful(value)
              }
          )
    )
)
  

Комментарии:

1. Результат преобразования является входом для следующего?

2. Результат преобразования является входом для следующего? — Да, создание цепочки преобразований путем их компоновки, насколько я понимаю

3. Я думаю, я догадываюсь… это потому, что я не обрабатываю вариант, в котором acc initial терпит неудачу

Ответ №1:

Похоже, transformWith это не дает вам возможности восстановить исходное входное значение с предыдущего шага, потому что оно должно работать с a Try . Что он должен делать, если Try окажется ошибкой? К тому времени у него нет исходного ввода, к которому можно вернуться, у него есть только a Throwable , а не a T . Итак, transformWith кажется недостаточным.

Если конвейер занимает всего несколько преобразований, вы можете попробовать foldLeft с fallbackTo :

 import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

type Transformation[T] = T => Future[T]
def chainTrafos[T](
  trafos: List[Transformation[T]],
  value: T
): Future[T] = {
  trafos.foldLeft(Future { value })(
    (f, t) => f.flatMap(x => t(x).fallbackTo(Future { x }))
  )
}


val ta: Transformation[Int] = x => Future { x * x }
val tb: Transformation[Int] = x => Future.failed(new Error("oops"))
val tc: Transformation[Int] = x => Future { x - 58 }

println(Await.result(chainTrafos(List(ta, tb, tc), 10), 10.seconds))
  

С принтами

 42
  

Комментарии:

1. Отлично! Спасибо! это работает и с неудачным начальным будущим!

2. Отличный пример использования fallbackTo !