簡體   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