玩:如何改善错误处理并避免创建不必要的可抛出实例

3天

创建和引发异常是一项昂贵的工作……而且在Web应用程序中,根本不需要抛出异常。如果在控制器使用的服务类中发生错误,则抛出异常是有道理的……但是,如果控制器已经意识到问题(例如,未找到用户),则可以返回描述问题的JSON 。

解决方案可以是仅在必要时Error扩展案例类Throwable,即,当控制器调用的服务失败时:

object MyErrors {

  trait Error { def getMessage: String }
  final case class UserNotFound(userId: Strig) extends Error { def getMessage = s"user $userId not found" }
  final case class UserNotFoundException(userId: String) extends Throwable (s"user $userId not found") with Error
  final case class DuplicateKey(key: Strig) extends Error { def getMessage = s"key $key already exists" }
  final case class DuplicateKeyException(key: String) extends Throwable (s"key $key already exists") with Error
  ...
}

无论是否ErrorThrowable,我都可以处理以下可能的错误:

object Users extends Controller {

  ...

  def find(id: String) = Action { request =>
    userService.find(id).map {
      case Some(user) => Ok(success(user.toJson))
      case None =>
        // UserNotFound implements Error but does not inherits from Throwable
        errors.toResult(UserNotFound(id))
    }.recover { case e =>
      // e is thrown by userService.find() and extends Throwable and implements Error (e.g. DuplicateKeyException)
      errors.toResult(e)
    }
  }
}

errors.toResult地图当前异常或错误,以适当的HTTP结果(例如BadRequestNotFound等),并转换e到JSON -看到这个帖子的完整实现。

现在我的问题是:有没有那么复杂的方法可以做到这一点?如您所见,我必须为一个错误创建两个不同的案例类(在示例中,我为使事情简单起见,重复了两次错误消息)...

约翰南德伦

两种不同的想法:

如果异常的开销与堆栈跟踪有关,但是如果异常开销不那么高,您可能要使用异常,那么有一个用于异常的mixin将跳过在堆栈跟踪中生成 scala.util.control.NoStackTrace

如果更多是关于编写干净的FP代码(异常不适合且返回类型中包含所有可能的结果),则可以使用scala.util.Either(或减少冗长,例如,Or从scalactic库或\/ScalaZ中获取)。

Either您一起将Left视为失败和Right成功。然后有方便的方法可以在Option之间进行转换Either

val opt: Option[Int] = None
val either: Either[String, Int] = opt.toRight("Value for none/left")

如果您使用right投影,则您甚至可以进行理解,如果值不是,则会早退Right

val goodOrBad1: Either[String, Int] = Right(5)
val goodOrBad2: Either[String, Int] = Left("Bad")

val result: Either[String, Int] = for {
  good1 <- goodOrBad1.right
  good2 <- goodOrBad2.right
} yield good1 + good2

// fails with first non Right
result == Left("Bad")

让我们假装userService.findcartService.find返回Option[Something],这意味着您可以执行以下操作:

def showCart(id: String) = Action { request =>
  val userAndCartOrError: Either[Error, (User, Cart)] = for {
    user <- userService.find(id).toRight(UserNotFound(id)).right
    cart <- cartService.findForUser(id).toRight(NoCart(id)).right
  } yield (user, cart)

  userAndCartOrError.fold(
    error => Errors.toResult(error),
    userAndCart => Ok(Json.toJson(userAndCart))
  )
}

当然,对于期货来说,它变得更加混乱,因为您不能将不同的monad混入同一理解中(Future Either

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何避免不必要的数据复制?

来自分类Dev

js如何避免不必要的点击

来自分类Dev

如何在C ++中使用右值引用避免不必要的实例

来自分类Dev

如何避免在for循环中使用Java不必要的对象创建

来自分类Dev

如何处理资源字典,这样它们就不会创建不必要的对象

来自分类Dev

如何避免R中不必要的for循环

来自分类Dev

如何避免在React中不必要的重新渲染?

来自分类Dev

如何通过Servlet获取文件,避免不必要的GET?

来自分类Dev

Swift /如何避免UITableView rowHeight更改为不必要的

来自分类Dev

改善代码的错误处理

来自分类Dev

避免不必要的负载(SSE / AVX)

来自分类Dev

如何使用 async/await 进行错误处理而不必等待

来自分类Dev

如何修复pylint错误“不必要的理解”

来自分类Dev

不必要的类实例化重复

来自分类Dev

如何改善我对此诺言链的错误处理?

来自分类Dev

创建不必要的吸气剂

来自分类Dev

如何避免单元测试中不必要的前提条件?

来自分类Dev

提交表单后如何避免不必要的URL地址更改?

来自分类Dev

如何避免不必要公司的FireStore与高速缓冲存储器读取

来自分类Dev

如何避免使用钩子在组件中进行不必要的渲染

来自分类Dev

Composer将安装意外的polyfill。如果不必要,如何避免安装它们?

来自分类Dev

如何避免在稀疏稀疏矩阵中插入不必要的零

来自分类Dev

如何在Cassandra中为数据建模以避免不必要的重复

来自分类Dev

当某些值被忽略时,如何避免迭代器实现中不必要的昂贵操作?

来自分类Dev

如何在我的自定义LinkedList实现中避免不必要的递归?

来自分类Dev

如何避免在Codeigniter中过多和不必要的数据库连接

来自分类Dev

提交表单后,如何避免不必要的URL地址更改?

来自分类Dev

解析文件时如何避免不必要地使用cat?

来自分类Dev

如何避免让webpack加载不必要的软件包文件?

Related 相关文章

  1. 1

    如何避免不必要的数据复制?

  2. 2

    js如何避免不必要的点击

  3. 3

    如何在C ++中使用右值引用避免不必要的实例

  4. 4

    如何避免在for循环中使用Java不必要的对象创建

  5. 5

    如何处理资源字典,这样它们就不会创建不必要的对象

  6. 6

    如何避免R中不必要的for循环

  7. 7

    如何避免在React中不必要的重新渲染?

  8. 8

    如何通过Servlet获取文件,避免不必要的GET?

  9. 9

    Swift /如何避免UITableView rowHeight更改为不必要的

  10. 10

    改善代码的错误处理

  11. 11

    避免不必要的负载(SSE / AVX)

  12. 12

    如何使用 async/await 进行错误处理而不必等待

  13. 13

    如何修复pylint错误“不必要的理解”

  14. 14

    不必要的类实例化重复

  15. 15

    如何改善我对此诺言链的错误处理?

  16. 16

    创建不必要的吸气剂

  17. 17

    如何避免单元测试中不必要的前提条件?

  18. 18

    提交表单后如何避免不必要的URL地址更改?

  19. 19

    如何避免不必要公司的FireStore与高速缓冲存储器读取

  20. 20

    如何避免使用钩子在组件中进行不必要的渲染

  21. 21

    Composer将安装意外的polyfill。如果不必要,如何避免安装它们?

  22. 22

    如何避免在稀疏稀疏矩阵中插入不必要的零

  23. 23

    如何在Cassandra中为数据建模以避免不必要的重复

  24. 24

    当某些值被忽略时,如何避免迭代器实现中不必要的昂贵操作?

  25. 25

    如何在我的自定义LinkedList实现中避免不必要的递归?

  26. 26

    如何避免在Codeigniter中过多和不必要的数据库连接

  27. 27

    提交表单后,如何避免不必要的URL地址更改?

  28. 28

    解析文件时如何避免不必要地使用cat?

  29. 29

    如何避免让webpack加载不必要的软件包文件?

热门标签

归档