我如何掌握 Scala Future 中抛出的异常? [英] How do I get hold of exceptions thrown in a Scala Future?

查看:25
本文介绍了我如何掌握 Scala Future 中抛出的异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力回答是否有标准的 Scala 函数来运行带有超时的块?, 如果在 Future 中抛出异常,就会遇到问题.

I've been working up my answer to Is there a standard Scala function for running a block with a timeout?, and have run into a problem if an exception is thrown in a Future.

  def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
    awaitAll(timeoutMs, future(f)).head.asInstanceOf[Option[T]]
  }

这样

runWithTimeout(50) { "result" } should equal (Some("result"))
runWithTimeout(50) { Thread.sleep(100); "result" } should equal (None)

但是如果我在我的块中抛出异常,它不会泄漏,而是被吞下 - 因此以下失败并显示..没有抛出异常"

But if I throw an exception in my block it doesn't leak, but is swallowed - so that the following fails with "..no exception was thrown"

intercept[Exception] {
    runWithTimeout(50) { throw new Exception("deliberate") }
}.getMessage should equal("deliberate")

Syserr 有一个带有消息的堆栈跟踪

Syserr has a stack trace with the message

<function0>: caught java.lang.Exception: deliberate

但我在 Scala 运行时中找不到打印的位置.

but I can't find where in the Scala runtime that is printed.

除了将 f 包装在另一个块中以捕获异常并在抛出时传播它们,还有什么方法可以说服 awaitAll 和/或 Future 抛出?

Apart from wrapping f in another block which catches exceptions and propagates them if thrown, is there any way to persuade awaitAll and/or Future to throw?

推荐答案

简短回答:否.

当您在线程上下文中工作时,异常不会做您想做的事,因为您想知道调用者中的异常,而异常发生在未来的线程中.

Exceptions don't do what you want when you're working in a threaded context, because you want to know about the exception in the caller, and the exception happens in the future's thread.

相反,如果你想知道异常是什么,你应该返回一个Either[Exception,WhatYouWant]——当然,你必须在未来捕捉到那个异常并打包.

Instead, if you want to know what the exception was, you should return an Either[Exception,WhatYouWant]--of course, you have to catch that exception within the future and package it up.

scala> scala.actors.Futures.future{
  try { Right("fail".toInt) } catch { case e: Exception => Left(e) }
}
res0: scala.actors.Future[Product with Serializable with Either[Exception,Int]] = <function0>

scala> res0()   // Apply the future
res1: Product with Serializable with Either[Exception,Int] =
      Left(java.lang.NumberFormatException: For input string: "fail")

这篇关于我如何掌握 Scala Future 中抛出的异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆