为什么Future.onSuccess未来不会失败?

时间:2016-07-05 20:05:07

标签: scala future

假设我想在未来完成后对结果进行一些验证:

 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
  }

2 个答案:

答案 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

     

如果当前的未来失败,那么结果未来也会失败。

如果您需要一个不同的例外,您只需将collecttransform链接起来:

transform(identity, _ => new NothingInterestingFound())