繁体   English   中英

将EitherT[Future, A, B] 转换为Option[B]

[英]Convert EitherT[Future, A, B] to Option[B]

我有一个方法

def getInfoFromService(reqParams: Map[String, String]): Future[Either[CustomException, A]] 

我还有另一个功能

import cats.implicits._
def processInfoAndModelResponse(input: Future[Either[CustomException, A]]): Option[A] = {
    for {
         either <- input
         resultA <- either
     } yield resultA.some
}

所以基本上,我试图将Future[Either[CustomException, A]])Option[A] resultA <- either在上面的代码中都不起作用,因为地图对类型不满意。

你尝试做的基本上是这样的

def convert[A](future: Future[Either[CustomException, A]]): Option[A] =
  Try(Await.result(future, timeout)).toEither.flatten.toOption

这个:

  • 丢失有关错误的信息,这会阻止任何调试(尽管您可以在.flatten之后.flatten
  • 阻止异步操作,这首先会扼杀使用Future任何好处

Monad 不会那样工作。 基本上,您可以使用for为同一个 monad 处理多个 monadic 计算,但是FutureEither是不同的 monad。

尝试

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._

def processInfoAndModelResponse(input: Future[Either[CustomException, A]]): Option[A] = {
  Await.result(input, 1.minute).toOption
}

@MateuszKubuszok的答案不同,因为它不会抛出。

您不能明智地将Future[Either[CustomException, A]]Option[A] ,因为在 Future 完成之前您不知道结果会是什么。

Future[Either[CustomException, A]]可能只是打赌保持这种方式,或者将 IO 作为IO[Either[CustomException, A]] 如果您不关心CustomException ,您也可以捕获它Future (或IO )错误处理机制,或者完全丢弃它。

一些选项:

在 Future 的错误处理中吸收 CustomException:

val fa: Future[A] = fut.transform(_.map(_.toTry))

忽略 CustomException 并使 Future 返回 None

val fa: Future[Option[A]] = fut.map(_.toOption)

如果你真的想阻塞一个线程并等待结果,

Await.result(input, Duration.Inf).toOption

但所有等待的警告都适用。 请参阅此处复制的文档

警告:强烈建议不要提供过长的超时,因为调用线程的进程将被挂起——阻塞——直到 Awaitable 有结果或超时到期。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM