nma*_*mat 5 api error-handling scala exception
我正在为 API 编写包装器,我想对应用程序问题进行错误处理。每个请求都返回一个 Future,所以为了做到这一点,我看到 2 个选项:使用 aFuture[Either]或使用异常立即使未来失败。
这是两种情况的片段,response是返回 HTTP 请求的未来:
def handleRequestEither: Future[Either[String, String]] = {
response.map {
case "good_string" => Right("Success")
case _ => Left("Failed")
}
}
def handleRequest: Future[String] = {
response.map {
case "good_string" => "Success"
case _ => throw new Exception("Failed")
}
}
Run Code Online (Sandbox Code Playgroud)
这是在两种情况下获得结果的代码段:
handleRequestEither.onComplete {
case Success(res) =>
res match {
case Right(rightRes) => println(s"Success $res")
case Left(leftRes) => println(s"Failure $res")
}
case Failure(ex) =>
println(s"Failure $ex")
}
handleRequest.onComplete {
case Success(res) => println(s"Success $res")
case Failure(ex) => println(s"Failure $ex")
}
Run Code Online (Sandbox Code Playgroud)
我不喜欢使用异常,但使用Future[Either]会使之后获得响应变得更加冗长,如果我想将结果映射到另一个对象,它会变得更加复杂。这是要走的路,还是有更好的选择?
让我解释一下 Erik Meijer 并考虑下表:
然后考虑语言构造的这两个特征:数量(它是否聚合一个或多个项目?)和模式(在准备好之前阻塞读取操作时同步,或者在未准备好时异步)。
所有这些都意味着Try构造和块同步管理生成结果的块的成功或失败。您将控制您的资源是否提供正确的答案,而不会遇到问题(异常描述的问题)。
另一方面 aFuture是一种异步Try。这意味着当没有发现问题(异常)时它会成功完成,然后通知其订阅者。因此,我认为在这种情况下你不应该有 futureEither,那就是你的第二个handleRequest实现是使用 future 的正确方法。
最后,如果抛出异常让您感到不安,您可以遵循以下方法Promises:
def handleRequest: Future[String] = {
val p = Promise[String]
response.map {
case "good_string" => p.success("Success")
case _ => p.failure(new Exception("Failed"))
}
p.future
}
Run Code Online (Sandbox Code Playgroud)
或者:
case class Reason(msg: String) extends Exception
def handleRequest: Future[String] = {
val p = Promise[String]
response.map {
case "good_string" => p.success("Success")
case _ => p.failure(Reason("Invalid response"))
}
p.future
}
Run Code Online (Sandbox Code Playgroud)
我宁愿使用你的第二种方法。