Scala与多个未来合作

时间:2015-03-24 16:44:33

标签: scala akka

我有两个返回List[Int]

的数据源
// first work with postgresql database

object Db {

  def get: Future[List[Int]] = // impl

}
// second it's remote service
object Rs {
  def get: Future[List[Int]] = // impl
}

然后我想返回两个列表。但我不知道如何处理异常:

  1. Db可能抛出ConnectionUnavailable

  2. 远程服务 - 错误请求或InternalServer错误

  3. 两者 - TimeoutException

  4. 但是,当我只有db的结果时,我想返回它。如果我有来自db和远程服务的结果,我想返回两个列表的总和。

    如何使用此案例?

2 个答案:

答案 0 :(得分:5)

val total: Future[Int] =
  Db.get.flatMap { dbResults =>
    Rs.get.map { remoteResults =>
      dbResults.sum + remoteResults.sum
    }
  }

或等效

   val total: Future[Int] = for {
     dbResults <- Db.get
     remoteResults <- Rs.get
   } yield dbResults.sum + remoteResults.sum

为了清楚起见,我明确注释了结果类型,但没有必要。

totalFuture[Int]持有成功或失败的计算。如果您需要处理错误,可以在其上附加onFailure处理程序。例如

total.onFailure {
  case e: TimeoutException => // ...
  case e: ConnectionError  => // ...
}

(组成例外的名称)

答案 1 :(得分:2)

您需要合并flatMaprecover

for {
  db <- Db.get
  rs <- Rs.get.recover { 
    case e =>
      logger.error("Error requesting external service", e)
      List.fill(db.length)(0)
  }
} yield (db, rs).zipped.map(_+_).sum

如果你愿意,你可以调整转换(我假设你的意思是元素的列表总和),但基本的想法保持不变 - 如果你想要&#34;忽略&#34;未来的失败,你需要在其上调用recover

如果需要,可以从for理解中提取恢复函数,但仍然必须在其中调用recover

def handler(n: Int): PartialFunction[Throwable, List[Int]] = {
  case e =>
    logger.error("Error requesting external service", e)
    List.fill(n)(0)
}

for {
  db <- Db.get
  rs <- Rs.get.recover(handler(db.length))
} yield (db, rs).zipped.map(_+_).sum