2014-05-06 38 views
0

任何想法为什么下面的代码可以处理Success没有任何问题,但当试图返回Failure最终扔Exception无法从scala接收失败未来

异常线程 “main” au.com.ingdirect.splunk.Implicits.package $ LameExcuse:你好 在au.com.ingdirect.splunk.Implicits.package $ RichJob $$ anonfun $ asFuture $ 1.适用(包.scala:42) at au.com.ingdirect.splunk.Implicits.package $ RichJob $$ anonfun $ asFuture $ 1.apply(package.scala:36) at 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 

    } 
} 

感谢

+0

我没有看到代码的任何错误。你能解释stacktrace究竟在哪里抛出异常吗.. – Jatin

+0

LameExcuse扩展异常,试图摆脱这一点。顺便说一句:'新'对于案例班来说毫无用处! –

回答

2

我认为您的问题的一部分是,在Main.scala中,您在注册非阻塞onComplete回调之前首先执行阻止Await.result。如果Await.result,如果Future失败,无论是例外Failure将包装将被抛出。所以,就你的情况而言,如果Future失败,你将永远无法获得注册onComplete回调的代码。如果您删除了Await.result,那么事情应该按照您的预期工作,更优雅地失败并在onComplete回调中触发您的Failure案例。

另外,在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 
    } 
}