无法从scala Future收到失败

时间:2014-05-06 06:16:57

标签: scala promise future

任何想法为什么下面的代码可以处理Success而没有任何问题,但在尝试返回Failure时最终会抛出Exception

线程中的异常“main”au.com.ingdirect.splunk.Implicits.package $ LameExcuse:hello     at au.com.ingdirect.splunk.Implicits.package $ RichJob $$ anonfun $ asFuture $ 1.apply(package.scala:42)     at au.com.ingdirect.splunk.Implicits.package $ RichJob $$ anonfun $ asFuture $ 1.apply(package.scala:36)     在scala.concurrent.impl.Future $ PromiseCompletingRunnable.liftedTree1 $ 1(Future.scala:24)

这是我的代码:

/* --- Main.scala --- */
import test.Implicits._
val job = service.createJob("search immediatePayment", queryArgs)
Await.result(job, 10 seconds)

job.onComplete{
    case Success(j) => println("Success!!")
    case Failure(l: LameExcuse) => println("Why I never fall here?") 
}

/* --- package.scala ---*/
package object Implicits {
implicit val executorService = Executors.newFixedThreadPool(4)
implicit val executionContext = ExecutionContext.fromExecutorService(executorService)

case class LameExcuse(msg: String) extends Exception(msg)

implicit class RichJob(val job: Job) {
  def asFuture(): Future[Job] = {
    // I promise i will return a completed Job
    val p = Promise[Job]()
    val fail = false
    // ... and here i am
    future {       
        while (!job.isDone()) {
          Thread.sleep(1000)
        }
        if (fail)
          p failure (new LameExcuse("Service unavailable")) //<-- This will print the stacktrace on the console, but it will not send a Failure
        else
          p success job //<-- This works fine
    } 
    p.future

  }
}

由于

1 个答案:

答案 0 :(得分:2)

我认为您的部分问题是在Main.scala中,您首先在注册非阻塞Await.result回调之前执行了阻止onComplete。使用Await.result,如果Future失败,Failure包装的任何异常都将被抛出。因此,在您的情况下,如果Future失败,您将永远无法访问注册onComplete回调的代码。如果您删除了Await.result,那么事情应该按照您的预期运行,更优雅地失败,并在Failure回调中遇到onComplete案例。

此外,在asFuture中,我不确定您为什么需要Promise。您已经创建了Future并且可以返回该内容而不是使用Promise。您的代码可以简化为:

def asFuture(): Future[Job] = {
  val fail = false
  future {       
      while (!job.isDone()) {
        Thread.sleep(1000)
      }
      if (fail)
        throw new LameExcuse("Service unavailable")          
      job
  } 
}