假设我想在未来完成后对结果进行一些验证:
def futureUser() {
val foo = Future(getUserData(userId))
foo.onSuccess {
case None => throw new InvalidUserId(userId)
}
foo // This sucks too btw: why doesn't `onSuccess` return `this` ???
}
这根本不会像它一样:futureUser
返回成功的Future
None
,异常被转储到控制台并“swallen”。
看起来这实际上是故意这样做的(推特期货的行为方式相同......除了,至少,.onSuccess
是“可链接的”)。为什么?这是什么原因?
更新好的,我需要提一下,这里仅使用Option
作为示例。请考虑一下:
def futureItems() = Future(getInterestingItems()).map {
case Nil => throw new NothingInterestingFound()
case bar => bar // <-- this is the ugly piece that I could avoid if .onSuccess did not swallow failures
}
答案 0 :(得分:0)
如何写这个:
foo map { _.getOrElse(throw new Exception()) }
如评论中所述,onSuccess
仅在您不关心结果时才有用(只有副作用很重要)。
例如,您可以在onSuccess
中进行一些登录。发送电子邮件也很有意义(你想在成功的时候发送它,但你不需要等待发送完成)。
答案 1 :(得分:0)
如果您只想对成功的Future
进行验证,那么您只需要transform
:
Future(getInterestingItems()).transform(validate, identity)
甚至可以很好地加糖:
implicit class FutureFailureTransform[T](private val f: Future[T]) extends AnyVal {
def validated(isValid: T => T): Future[T] = {
f.transform(isValid, identity)
}
}
// Use
Future(getInterestingItems()).validated {
case Nil => throw new NothingInterestingFound()
}
或者,如果您使用NoSuchElementException
就可以了,可以使用Future.collect
:
Future(getInterestingItems()) collect {
case InterestingCase(data) => // Do stuff here
}
如果当前的未来包含定义了部分函数的值,则新的未来也将保留该值。否则,生成的未来将失败并显示
NoSuchElementException
。如果当前的未来失败,那么结果未来也会失败。
如果您需要一个不同的例外,您只需将collect
与transform
链接起来:
transform(identity, _ => new NothingInterestingFound())