#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
infutureValue: Future[Value]
inmethodC
? ЕслиmethodC
бы было принято aValue
, это было бы намного элегантнее.
Ответ №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