任何想法为什么下面的代码可以处理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
}
}
由于
答案 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
}
}