Как получить Future[Right] из Future[Либо [Left, Right]] в Scala?

#scala #future #either

#scala #будущее #либо

Вопрос:

У меня есть два метода, которые уже существуют:

 def methodB(): Future[Either[Error, Value]]




def methodC(futureValue: Future[Value]): Future[Value]
  

И мне нужен метод, который получит результат methodB и установит правильное значение methodC , но оно должно быть Future:

 def methodA(): Future[Either[Error, Value]] = {
    val resultFromB: Future[Either[Error, Value]] = methodB()
    // get Future[Value] from resultFromB and put it to methodC

    resultFromB
  }
  

Не могли бы вы помочь? Может быть, как преобразовать Future[Either[Error, Value]] в Either[Future[Error], Future[Value]] ?

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

1. Вы уверены, что не можете избавиться от Future in futureValue: Future[Value] in methodC ? Если methodC бы было принято a Value , это было бы намного элегантнее.

Ответ №1:

Получить Future[Value] from Future[Either[Error, Value]] просто, хотя вам нужно значение по умолчанию, если оно Left , а не Right :

 val default: Value = ???
val res: Future[Value] = resultFromB.map(_.getOrElse(default))
  

Преобразование Future[Either[Error, Value]] в Either[Future[Error], Future[Value]] бессмысленно, потому что вы не можете решить, является ли outer Either Left или Right пока оригинал Future не будет завершен, и в этом случае нет смысла создавать внутренние значения Future .

Ответ №2:

Поскольку Future может произойти сбой, вы могли бы написать:

 def fright[A,B](fab: Future[Either[A,B]]): Future[B] = 
  fab.flatMap(ab => ab.fold(b => Future.failed(new Throwable("t'was left")), b => Future(b)))
  

Ответ №3:

Как Future и случаи сбоя и успеха, соответствующие Either ‘s Left и Right, вы можете просто использовать —

 methodB() flatMap {
    case Left(ex) => Future.failed(ex)
    case Right(v) => Future.successful(v)
}
  

Это вернет вам Future[Value]

Ответ №4:

В качестве дополнения к другим ответам, если вы используете cats и Error являетесь подклассом Throwable , вы можете просто использовать rethrow :

 import cats.implicits._


val result: Future[Value] = resultFromB.rethrow