Scala 与多个未来一起工作
Scala work with multiple futures
我有两个数据源,returns 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
}
然后我想要 return 两个列表。但我不知道如何处理异常:
Db 可能抛出 ConnectionUnavailable
远程服务 - 错误请求,或内部服务器错误
两者 - TimeoutException
但是,当我只有来自数据库的结果时,我想 return 它。如果我有来自数据库和远程服务的结果,我想 return 两个列表的总和。
如何处理这个案例?
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
为了清楚起见,我明确注释了结果类型,但这不是必需的。
total
是一个 Future[Int]
持有成功或失败的计算。如果您需要处理错误,您可以在其上附加一个 onFailure
处理程序。例如
total.onFailure {
case e: TimeoutException => // ...
case e: ConnectionError => // ...
}
(例外的名字是编的)
您需要合并 flatMap
和 recover
:
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
如果你愿意,你可以调整转换(我假设你的意思是列表的逐元素总和),但基本思想保持不变 - 如果你想 "ignore" 某些未来的失败,你需要在上面调用 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
我有两个数据源,returns 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
}
然后我想要 return 两个列表。但我不知道如何处理异常:
Db 可能抛出 ConnectionUnavailable
远程服务 - 错误请求,或内部服务器错误
两者 - TimeoutException
但是,当我只有来自数据库的结果时,我想 return 它。如果我有来自数据库和远程服务的结果,我想 return 两个列表的总和。
如何处理这个案例?
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
为了清楚起见,我明确注释了结果类型,但这不是必需的。
total
是一个 Future[Int]
持有成功或失败的计算。如果您需要处理错误,您可以在其上附加一个 onFailure
处理程序。例如
total.onFailure {
case e: TimeoutException => // ...
case e: ConnectionError => // ...
}
(例外的名字是编的)
您需要合并 flatMap
和 recover
:
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
如果你愿意,你可以调整转换(我假设你的意思是列表的逐元素总和),但基本思想保持不变 - 如果你想 "ignore" 某些未来的失败,你需要在上面调用 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