Scala:链接期货,返回第一个
Scala: Chaining futures, returning the first
我有一个场景,我有一个 Future[Something]
: a
当成功时 需要触发第二个 Future[Unit]
: b
。我想将 a
和 b
链接在一起,但我只关心 a
是否成功。如果 b
失败,我可以记录一个错误并保留它:
到目前为止我有:
def updateSomething(something: Something): Future[Something] = {
val eventual: Future[Something] = repository.update(something)
eventual.onSuccess({
case updated =>
repository.audit(updated.id, "Update successful")
.onFailure({
case throwable: Throwable => Logger.error("Audit failed", throwable)
})
Logger.info("Update Complete")
})
eventual
}
但这并不 link update
和 audit
的生命周期在一起。例如,当我 Await.result(service.updateSomething(...), duration)
时,无法保证 repository.audit
未来已经完成。
flatMap
是你的朋友。你可以只使用 for-comprehension + recover:
for {
a <- executeA()
_ <- executeB(b).recover{case e => println(e); Future.unit } // awaits B to complete
} yield a
你也可以使用更友好的形式:
execudeA().flatMap(a =>
executeB().recover { case e => println(e); () }.map(_ => a)
)
此外,您可以只使用一个 val
val = a <- executeA()
a.andThen{ case _ => executeB(b).recover{case e => println(e)} }
a //and return a
我有一个场景,我有一个 Future[Something]
: a
当成功时 需要触发第二个 Future[Unit]
: b
。我想将 a
和 b
链接在一起,但我只关心 a
是否成功。如果 b
失败,我可以记录一个错误并保留它:
到目前为止我有:
def updateSomething(something: Something): Future[Something] = {
val eventual: Future[Something] = repository.update(something)
eventual.onSuccess({
case updated =>
repository.audit(updated.id, "Update successful")
.onFailure({
case throwable: Throwable => Logger.error("Audit failed", throwable)
})
Logger.info("Update Complete")
})
eventual
}
但这并不 link update
和 audit
的生命周期在一起。例如,当我 Await.result(service.updateSomething(...), duration)
时,无法保证 repository.audit
未来已经完成。
flatMap
是你的朋友。你可以只使用 for-comprehension + recover:
for {
a <- executeA()
_ <- executeB(b).recover{case e => println(e); Future.unit } // awaits B to complete
} yield a
你也可以使用更友好的形式:
execudeA().flatMap(a =>
executeB().recover { case e => println(e); () }.map(_ => a)
)
此外,您可以只使用一个 val
val = a <- executeA()
a.andThen{ case _ => executeB(b).recover{case e => println(e)} }
a //and return a