处理Scala的错误:理解的未来
我想在我的play
scala web应用程序中进行错误处理.
我的应用程序与数据库进行交谈,以获取一些行,它遵循以下流程. >首先调用db来获取一些数据 下面是我的伪代码 def getResponse(name: String) (implicit ctxt: ExecutionContext): Future[Response] = { for { future1 <- callFuture1(name) future2 <- callFuture2(future1.data) future3 <- callFuture3(future1.data,future2.data) } yield future3 } 上述理解中的每种方法都会返回未来,这些方法的签名如下. private def callFuture1(name: String) (implicit ctxt: ExecutionContext): Future[SomeType1] {...} private def callFuture2(keywords: List[String]) (implicit ctxt: ExecutionContext): Future[SomeType2] {...} private def callFuture3(data: List[SomeType3],counts: List[Int]) (implicit ctxt: ExecutionContext): Future[Response] {...} 在以下情况下,如何进行错误/故障处理 当callFuture1无法从数据库中获取数据时.我想回来 – 编辑 – 我正在尝试从getResponse()方法返回一个适当的错误响应,当任何一个callFuture失败,并且不会继续进行后续的futureCalls. 我尝试了以下,基于Peter Neyens的回答,但给了我一个运行时错误.. def getResponse(name: String) (implicit ctxt: ExecutionContext): Future[Response] = { for { future1 <- callFuture1(name) recoverWith { case e:Exception => return Future{Response(Nil,Nil,e.getMessage)} } future2 <- callFuture2(future1.data) future3 <- callFuture3(future1.data,future2.data) } yield future3 } 运行时错误我得到 ERROR] [08/31/2015 02:09:45.011] [play-akka.actor.default-dispatcher-3] [ActorSystem(play)] Uncaught error from thread [play-akka.actor.default-dispatcher-3] (scala.runtime.NonLocalReturnControl) [error] a.a.ActorSystemImpl - Uncaught error from thread [play-akka.actor.default-dispatcher-3] scala.runtime.NonLocalReturnControl: null 解决方法
您可以使用
Future.recoverWith 功能,如果未来失败,则自定义异常.
val failed = Future.failed(new Exception("boom")) failed recoverWith { case e: Exception => Future.failed(new Exception("A prettier error message",e) } 这将导致理解略微恶化: for { future1 <- callFuture1(name) recoverWith { case npe: NullPointerException => Future.failed(new Exception("how did this happen in Scala ?",npe)) case e: IllegalArgumentException => Future.failed(new Exception("better watch what you give me",e)) case t: Throwable => Future.failed(new Exception("pretty message A",t)) } future2 <- callFuture2(future1.data) recoverWith { case e: Exception => Future.failed(new Exception("pretty message B",e)) } future3 <- callFuture3(future1.data,future2.data) recoverWith { case e: Exception => Future.failed(new Exception("pretty message C",e)) } } yield future3 请注意,如果要添加更多信息而不仅仅是错误消息,您还可以定义自己使用的异常而不是Exception. 如果您不希望细粒度控制根据失败的未来中的Throwable设置不同的错误消息(如callFuture1),则可以使用隐式类来丰富Future,从而更简单地设置自定义错误消息: implicit class ErrorMessageFuture[A](val future: Future[A]) extends AnyVal { def errorMsg(error: String): Future[A] = future.recoverWith { case t: Throwable => Future.failed(new Exception(error,t)) } } 你可以使用如下: for { future1 <- callFuture1(name) errorMsg "pretty A" future2 <- callFuture2(future1.data) errorMsg "pretty B" future3 <- callFuture3(future1.data,future2.data) errorMsg "pretty C" } yield future3 在这两种情况下,直接使用errorMsg或recoverWith,您仍然依赖Future,因此如果将来未来失败,则将不会执行以下Futures,您可以直接在失败的Future中使用错误消息. 您没有指定如何处理错误消息.如果你想使用错误信息创建一个不同的响应,你可以使用recoverWith或recover. future3 recover { case e: Exception => val errorMsg = e.getMessage InternalServerError(errorMsg) } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |