我不明白@Falmarri 说什么,恕我直言,在 Future 中抛出异常会返回失败的 Future(顺便说一下,这是我期望的工作方式)仅仅是因为异常被捕获(老派 java 尝试抓住)
考虑 Scala 2.12
当您使用apply 方法(Future { } 是Future.apply 的语法糖)创建Future 时,您实际上是mapping a successful Future。
val unit: Future[Unit] = successful(())
def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] = unit.map(_ => body)
map 是对 transform 的调用
def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = transform(_ map f)
DefaultPromise 中的 transform 的 implementation 对非致命异常进行了尝试捕获
override def transform[S](f: Try[T] => Try[S])(implicit executor: ExecutionContext): Future[S] = {
val p = new DefaultPromise[S]()
onComplete { result => p.complete(try f(result) catch { case NonFatal(t) => Failure(t) }) } // Here is the magic
p.future
}
你可以试试在onComplete那一行加断点,然后再做
Future { throw new Exception("!") } // or Future.apply(throw new Exception("!")) or Future.unit.map(_ => throw new Exception("!"))
try f(result) 将调用 Success 的 map 函数,将其传递给您的函数(因为 Future.unit 的值是 Success(()) ),因为您的函数抛出异常,它将被 catch { case NonFatal(t) => Failure(t) } 捕获
flatMap 会发生类似的情况,但在本例中是 calls transformWith
def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S] = transformWith {
case Success(s) => f(s)
case Failure(_) => this.asInstanceOf[Future[S]]
}
transformWithalso does 尝试捕获
override def transformWith[S](f: Try[T] => Future[S])(implicit executor: ExecutionContext): Future[S] = {
val p = new DefaultPromise[S]()
onComplete {
v => try f(v) match {
case fut if fut eq this => p complete v.asInstanceOf[Try[S]]
case dp: DefaultPromise[_] => dp.asInstanceOf[DefaultPromise[S]].linkRootOf(p)
case fut => p completeWith fut
} catch { case NonFatal(t) => p failure t } // Here is the magic
}
p.future
}
不过我不是 scala 专家,只是做了一些调试,所以不要把我说的当成理所当然。