执行以下操作的最惯用和最简洁的方法是:根据以前的执行情况执行或未执行的未来,如下所示:
def getItFromHere : Future[Option[Something]] = ...
def getItFromThere : Future[Option[Something]] = ...
def getIt : Future[Option[Something]] = {
for {
maybeSomething <- getItFromHere
probablySomething <- maybeSomething.getOrElse(getItFromThere) // Obviously can't be done!!!
}
yield probablySomething
}
特定用例示例: 从缓存中获取一个项目,只有在缓存中找不到它,才能从数据库中获取它。
我在这里假设getItFromHere
和getItFromThere
不会因异常而失败。他们将返回Some [Something]或None。请随意考虑这一假设,或者在没有它的情况下给予更好的假设。
注意:我理解for-comprehension的内部机制,它实际上是内部转换为map / flatMap / filter。
答案 0 :(得分:6)
如果在缓存中找不到任何项目,然后通过检索恢复它,您可能会失败。
// assuming getItFromHere() fails if no item is found
getItFromHere() recoverWith { case _ => getItFromThere() }
或者使用Option
你可以这样做:
getItFromHere() flatMap {
case Some(x) => Future.successful(Some(x))
case None => getItFromThere()
}
答案 1 :(得分:2)
其实你的例子几乎就在那里。您只需要匹配monadic组合所期望的Future类型:
for {
fut <- someFuture
something <- fut.map(x=>someFuture).getOrElse(someBetterFuture)
} yield something
为简单起见,此处someFuture
为val
。如果您使用def
,请避免重新计算操作,方法是将结果打包回以后。折叠到问题代码中:
for {
maybeSomething <- getItFromHere
probablySomething <- maybeSomething.map(x=> Future.succcessful(maybeSomething)).getOrElse(getItFromThere)
} yield probablySomething
答案 2 :(得分:2)
如果你使用scalaz的OptionT变换器:
def getItFromHere : OptionT[Future,Something] = OptionT(...)
def getItFromThere : OptionT[Future,Something] = OptionT(...)
def getIt : Future[Option[Something]] = (getItFromHere orElse getItFromThere).run