抛出异常在future.map scala 中不起作用?

heh*_*eda 5 scala future

def testThrowException(number: Int): Future[Int] = {
 if (number == 0) {
     throw new Exception("number is 0")
 else {
     Future{1}
 }
Run Code Online (Sandbox Code Playgroud)

对于上述函数,如果我用 testThrowException(0) 调用它,我可以看到控制台中打印的异常错误消息,但如果我执行类似的操作

def testThrowException(number: Int): Future[Int] = {
anotherFuture.map {
    if (number == 0) {
        throw new Exception("number is 0")
    } else {
        1
    }
}
Run Code Online (Sandbox Code Playgroud)

我看不到控制台中打印的异常,但是如果我执行 testThrowException.onFailure,我可以看到失败消息,我在这里做错了什么吗?为什么不打印出异常

Mar*_*lic 5

Future在一个单独的线程中运行,因此将 a 扔进去Future只会使该线程崩溃,同时保持主线程运行。例如,

object Hello extends App {
  println(s"Starting in main thread called ${Thread.currentThread.getName}...")
  Future(
    throw new RuntimeException(s"I crashed separate thread called ${Thread.currentThread.getName}")
  ).andThen { case Failure(e) => println(e.getMessage) }
  println("I made it!")
}
Run Code Online (Sandbox Code Playgroud)

应该输出

Starting in main thread called run-main-e...
I made it!
I crashed separate thread called scala-execution-context-global-253
Run Code Online (Sandbox Code Playgroud)

我们看到它scala-execution-context-global-253在主线程run-main-e保持运行的同时崩溃了单独的线程,所以I made it!打印得很好。另一方面,下面的例子抛出了一个Future

object Hello extends App {
  println(s"Starting in main thread called ${Thread.currentThread.getName}...")
  throw new RuntimeException(s"I crashed the main thread ${Thread.currentThread.getName}")
  println("I made it!")
}
Run Code Online (Sandbox Code Playgroud)

哪个输出

Starting in main thread called run-main-d...
[error] (run-main-d) java.lang.RuntimeException: I crashed the main thread run-main-d
Run Code Online (Sandbox Code Playgroud)

我们看到主线程run-main-d崩溃之前I made it!可以打印。


ELi*_*nda 3

第一个函数testThrowException在获取 a 作为输入的情况下不会返回 Future 0。因此,程序会一直运行,直到出现异常。

然而,如下面粘贴的源代码所示,Future.map总是返回另一个 future:

  def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = { // transform(f, identity)
    val p = Promise[S]()
    onComplete { v => p complete (v map f) }
    p.future
  }
Run Code Online (Sandbox Code Playgroud)

仅定义 Future 不会打印其结果,也不会打印抛出的异常。您需要定义onSuccessonFailure、 或onComplete来执行此操作。但是,如果 Future 的主体中存在 print 语句,那么它将执行:

def addOne(number: Int): Int = {
    if (number == 0) {
        // you can also print the exception instead of just throwing it.
        throw new Exception("number is 0")
    } else {
        println("success")
        1 + number
    }
}
Future { addOne(1) } // scala.concurrent.Future[Int] = Future(Success(2))
// the above also prints "success"
Future { addOne(0) } // scala.concurrent.Future[Int] = Future(Failure(java.lang.Exception: number is 0))
// the above does not print anything unless the exception is printed before thrown in `addOne`
Run Code Online (Sandbox Code Playgroud)

您还可以使用onComplete, 来处理成功和/或失败:

// prints "got error" plus the stack trace

 - List item

Future {0}.map(addOne).onComplete {
       case Success(value) => println(s"got $value")
       case Failure(t) => println("got error: " + t.getStackTrace.mkString("\n"))
     }
Run Code Online (Sandbox Code Playgroud)

请注意,使用的进口是:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
Run Code Online (Sandbox Code Playgroud)