在我的
scala代码中,我有一些嵌套的Try()匹配{},看起来很难看:
import scala.util._ Try(convertJsonToObject[User]) match { case Success(userJsonObj) => Try(saveToDb(userJsonObj.id)) match { case Success(user) => Created("User saved") case _ => InternalServerError("database error") } case _ => BadRequest("bad input") }
解决方法
有很多方法可以解决这个问题.我会给你一个可能性.考虑这个清理过的代码版本:
trait Result case class BadRequest(message:String) extends Result case class InternalServerError(message:String) extends Result case class Created(message:String) extends Result def processRequest(json:String):Result = { val result = for{ user <- Try(parseJson(json)) savedUser <- Try(saveToDb(user)) } yield Created("saved") result.recover{ case jp:JsonParsingException => BadRequest(jp.getMessage) case other => InternalServerError(other.getMessage) }.get } def parseJson(json:String):User = ... def saveToDb(user:User):User = ...
对此代码的警告是,它假定您可以通过每个可能产生的异常来区分json解析失败和db失败.虽然做出了不错的假设.此代码与java try / catch块非常相似,它捕获不同的异常类型,并根据捕获这些不同类型返回不同的结果.
关于这种方法的另一个好处是你可以为各种可能的异常定义一个标准的恢复部分函数,并在整个控制器中使用它(我假设这个代码是)来消除重复的代码.像这样的东西:
object ExceptionHandling{ val StandardRecovery:PartialFunction[Throwable,Result] = { case jp:JsonParsingException => BadRequest(jp.getMessage) case sql:sqlException => InternalServerError(sql.getMessage) case other => InternalServerError(other.getMessage) } }
然后在你的控制器中:
import ExceptionHandling._ result.recover(StandardRecovery).get