【问题标题】:Chain Scala Futures return type链 Scala 期货返回类型
【发布时间】:2014-09-05 03:52:50
【问题描述】:

我正在尝试在 Scala 中链接 Futures,但它给了我错误的返回类型。

我有以下方法:

  def getOneRecordByModel(x:DirectFlight): Future[Option[FlightByDetailModel]] = {
    select.allowFiltering().where(_.from eqs x.from).and(_.to eqs x.to).and(_.departure eqs x.departure).and(_.arrival eqs x.arrival).and(_.carrier eqs x.airline).and(_.code eqs x.flightCode).one()
  }
  def getRecordByUUID(x:FlightByDetailModel): Future[Option[FlightByUUIDModel]] = {
    select.allowFiltering().where(_.uuid eqs x.uuid).one()
  }

  def getUUIDRecordByModel(x:DirectFlight): Future[Option[FlightByUUIDModel]] = {
      getOneRecordByModel(x) andThen {
        case Success(Some(flight)) => getRecordByUUID(flight)
        case Success(x) => Success(x)
        case Failure(x) => Failure(x)
      }
    }

但现在我得到getUUIDRecordByModel返回类型为Future[Option[FlightByDetailModel]]的错误

如何正确链接它们?

【问题讨论】:

  • 当你使用 andThen 时你不会改变返回类型。您需要 flatMap 或 map 取决于其他方法的返回类型。
  • andThen 组合子纯粹是为了产生副作用。它总是返回被调用的Future,保持不变。正如其他人所提到的,map 和/或flatMap 应该是您正在寻找的。​​span>

标签: scala future


【解决方案1】:

我会改用flatMap

def getUUIDRecordByModel(x:DirectFlight): Future[Option[FlightByUUIDModel]] = {
    getOneRecordByModel(x) flatMap {
        case Some(flight) => getRecordByUUID(flight)
        case None => Future.successful(None)
    }
}

andThen 应用一个副作用函数并返回原始 Future,而不是内部的。

【讨论】:

    【解决方案2】:

    这个解决方案和上面的两个,实际上是相同的。他们提出了 flatMaps 组合的简单答案。这适用于一次性解决方案。

    for {
       oUuid <- getOneRecordByModel(x)
       oFlight <- oUuid.map(getRecordByUUID).getOrElse(Future.successful(None))
    } yield oFlight
    

    我怀疑鉴于方法签名,您将大量使用此策略。如果是这种情况,建议使用@Eugene Zhulenev 的上述回答(这是一个更实用的解决方案)。乍一看,Monad Transformers 可能看起来有点吓人,这里的代码块:

    val flightByUUID = for {
      flightByDetailModel <- optionT(getOneRecordByModel(x))
      flightByUUIDModel   <- optionT(getRecordByUUID(flightByDetailModel))
    } yield flightByUUIDModel
    
    flightByUUID.run  // this line grabs you a Future[Option[T]]
    

    非常简单,并且随着您开始增加复杂性而可扩展。希望这对您有所帮助。

    【讨论】:

    • 也可以,非常感谢。不幸的是,我只能选择一个正确的答案。
    【解决方案3】:

    你可以用 scalaz monad 转换器很好地做到这一点,更具体地说是 optionT。你可以reed一些不错的文章,更具体的你需要这个:http://eed3si9n.com/learning-scalaz/Monad+transformers.html#Monad+transformers

    这个好给:http://noelwelsh.com/programming/2013/12/20/scalaz-monad-transformers/

    def getOneRecordByModel(x:DirectFlight): Future[Option[FlightByDetailModel]] = ???
      def getRecordByUUID(x:FlightByDetailModel): Future[Option[FlightByUUIDModel]] = ???
    
      def getUUIDRecordByModel(x:DirectFlight): Future[Option[FlightByUUIDModel]] = {
        import scalaz.OptionT._
    
        val flightByUUID = for {
          flightByDetailModel <- optionT(getOneRecordByModel(x))
          flightByUUIDModel <- optionT(getRecordByUUID(flightByDetailModel))
        } yield flightByUUIDModel
    
        flightByUUID.run
      }
    

    为了能够将 optionT 与 scala.concurrent.Future 一起使用,您需要 Functor 和 Monad 实例在范围内

      import scala.concurrent.Future
    
        object FutureMonadAndFunctor {
    
        import scalaz.Monad
    
        implicit def FutureM(implicit ec: ExecutionContext): Monad[Future] = new Monad[Future] {
          def point[A](a: => A): Future[A] = Future(a)
          def bind[A, B](fa: Future[A])(f: (A) => Future[B]): Future[B] = fa flatMap f
        }
    
        implicit def FutureF(implicit ec: ExecutionContext): Functor[Future] = new Functor[Future]{
          def map[A, B](fa: Future[A])(f: (A) => B): Future[B] = fa map f
        }
      }
    
      import scala.concurrent.ExecutionContext.Implicits.global
    
      implicit val F = FutureMonadAndFunctor.FutureF
      implicit val M = FutureMonadAndFunctor.FutureM
    

    【讨论】:

    • 感谢您的洞察力。我现在已经多次遇到 Scalaz。我想现在是我学习的时候了。
    【解决方案4】:

    一个简单的解决方案是使用 flatMap 而不是 andThen 进行组合,后者专门用于处理副作用:

    getOneRecordByModel(x) flatMap { 
        ...
    }
    

    对于使用期货,我发现阅读 this page 几遍很有帮助。

    【讨论】:

      猜你喜欢
      • 2019-05-12
      • 2013-07-16
      • 1970-01-01
      • 2022-01-22
      • 2018-06-15
      • 2021-03-17
      • 2020-06-12
      • 2015-04-05
      • 2013-12-16
      相关资源
      最近更新 更多