【NestJS学习笔记】之 异常 && 异常过滤器前言,小编最近在学习NestJS系列相关知识,想把自己了解到的知识点作
前言,小编最近在学习NestJS系列相关知识,想把自己了解到的知识点作为笔记的同时也分享给大家,如果有哪里写的不好的恳请各位掘友批评指正谢谢,小编将不胜感激,闲话不多说,我们直接步入正题吧...
一. 在应用程序开发中,抛出异常是一种常见的处理错误和异常情况的方式。异常能够帮助我们识别和处理问题,提高应用程序的可靠性和可维护性。在NestJS中,我们可以利用异常机制来处理各种错误情况。
1.1 基础异常类
Nest
提供了一个内置的 HttpException
类,它从 @nestjs/common
包中导入。对于典型的基于HTTP
REST/GraphQL
API
的应用程序,最佳实践是在发生某些错误情况时发送标准HTTP响应对象。
在 CatsController
,我们有一个 findAll()
方法(GET
路由)。假设此路由处理程序由于某种原因引发异常。 为了说明这一点,我们在cats.controller.ts
中对其进行如下硬编码:
现在当客户端调用这个端点时,响应如下所示:
在上面的例子中,我们使用了 HttpStatus
。它是从 @nestjs/common
包导入的辅助枚举器。Nestjs 提供了标准的异常抛出,并且提供了很多的 http status 的定义,这样就不需要记特定的错误代码,只需要找到对应的文字即可。
export declare enum HttpStatus {
CONTINUE = 100,
SWITCHING_PROTOCOLS = 101,
PROCESSING = 102,
EARLYHINTS = 103,
OK = 200,
CREATED = 201,
ACCEPTED = 202,
NON_AUTHORITATIVE_INFORMATION = 203,
NO_CONTENT = 204,
RESET_CONTENT = 205,
PARTIAL_CONTENT = 206,
AMBIGUOUS = 300,
MOVED_PERMANENTLY = 301,
FOUND = 302,
SEE_OTHER = 303,
NOT_MODIFIED = 304,
TEMPORARY_REDIRECT = 307,
PERMANENT_REDIRECT = 308,
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
PAYMENT_REQUIRED = 402,
FORBIDDEN = 403,
NOT_FOUND = 404,
METHOD_NOT_ALLOWED = 405,
NOT_ACCEPTABLE = 406,
PROXY_AUTHENTICATION_REQUIRED = 407,
REQUEST_TIMEOUT = 408,
CONFLICT = 409,
GONE = 410,
LENGTH_REQUIRED = 411,
PRECONDITION_FAILED = 412,
PAYLOAD_TOO_LARGE = 413,
URI_TOO_LONG = 414,
UNSUPPORTED_MEDIA_TYPE = 415,
REQUESTED_RANGE_NOT_SATISFIABLE = 416,
EXPECTATION_FAILED = 417,
I_AM_A_TEAPOT = 418,
MISDIRECTED = 421,
UNPROCESSABLE_ENTITY = 422,
FAILED_DEPENDENCY = 424,
PRECONDITION_REQUIRED = 428,
TOO_MANY_REQUESTS = 429,
INTERNAL_SERVER_ERROR = 500,
NOT_IMPLEMENTED = 501,
BAD_GATEWAY = 502,
SERVICE_UNAVAILABLE = 503,
GATEWAY_TIMEOUT = 504,
HTTP_VERSION_NOT_SUPPORTED = 505
}
HttpException
构造函数有两个必要的参数来决定响应:
response
参数定义JSON
响应体。它可以是string
或object
,如下所述。status
参数定义HTTP
状态代码
默认情况下,JSON
响应主体包含两个属性:
statusCode
:默认为status
参数中提供的HTTP
状态代码message
:基于状态的HTTP
错误的简短描述
仅覆盖 JSON
响应主体的消息部分,请在 response
参数中提供一个 string
。
要覆盖整个 JSON
响应主体,请在response
参数中传递一个object
。 Nest
将序列化对象,并将其作为JSON
响应返回。
第二个构造函数参数-status
-是有效的 HTTP
状态代码。 最佳实践是使用从@nestjs/common
导入的 HttpStatus
枚举。
这是一个覆盖整个响应正文的示例:
使用上面的代码,响应如下所示:
1.2 自定义异常
对 Nestjs 的 HttpException 进行封装就可以自己定我们想要的异常抛出类。使用这种方法,Nest
可以识别我们自定义的异常,并自动处理错误响应。 让我们实现这样一个自定义异常:
由于 ForbiddenException
扩展了基础 HttpException
,它将和核心异常处理程序一起工作,因此我们可以在 findAll()
方法中使用它。
使用上面的代码,响应如下所示:
二. 异常过滤器
虽然基本(内置)异常过滤器可以为我们自动处理许多情况,但有时我们可能希望对异常层拥有完全控制权,例如,可能希望基于某些动态因素添加日志记录或使用不同的 JSON
模式。 异常过滤器正是为此目的而设计的。 它们可以控制精确的控制流以及将响应的内容发送回客户端。
让我们创建一个异常过滤器,它负责捕获作为HttpException
类实例的异常,并为它们设置自定义响应逻辑。为此,我们需要访问底层平台 Request
和 Response
。我们将访问Request
对象,以便提取原始 url
并将其包含在日志信息中。我们将使用 Response.json()
方法,使用 Response
对象直接控制发送的响应。
所有异常过滤器都应该实现通用的 ExceptionFilter<T>
接口。它需要我们使用有效签名提供 catch(exception: T, host: ArgumentsHost)
方法。T
表示异常的类型。@Catch()
装饰器绑定所需的元数据到异常过滤器上。它告诉 Nest
这个特定的过滤器正在寻找 HttpException
而不是其他的。在实践中,@Catch()
可以传递多个参数,所以我们可以通过逗号分隔来为多个类型的异常设置过滤器。
绑定过滤器:让我们将 HttpExceptionFilter
绑定到 CatsController
的 create()
方法上。@UseFilters()
装饰器需要从 @nestjs/common
包导入。
绑定该过滤器之后的响应结果如下:
我们在上面使用了 @UseFilters()
装饰器。和 @Catch()
装饰器类似,它可以使用单个过滤器实例,也可以使用逗号分隔的过滤器实例列表。 我们创建了 HttpExceptionFilter
的实例。另一种可用的方式是传递类(不是实例),让框架承担实例化责任并启用依赖注入。尽可能使用类而不是实例
。由于 Nest
可以轻松地在整个模块中重复使用同一类的实例,因此可以减少内存使用
。
推荐写法:
在上面的示例中,HttpExceptionFilter
仅应用于单个 create()
路由处理程序,使其成为方法范围的。 异常过滤器的作用域可以划分为不同的级别:方法范围,控制器范围或全局范围。 上面演示的是方法范围的过滤器,下面逐一举例
控制器范围,此结构为 CatsController
中的每个路由处理程序设置 HttpExceptionFilter
。
全局范围的过滤器:全局过滤器用于整个应用程序、每个控制器和每个路由处理程序。
就依赖注入而言,从任何模块外部注册的全局过滤器(使用上面示例中的 useGlobalFilters()
)不能注入依赖,因为它们不属于任何模块。为了解决这个问题,我们可以注册一个全局范围的过滤器直接为我们想要的模块设置过滤器,以根据需要将不同的过滤器应用于不同的模块,实现更细粒度的异常处理:
需要注意的是,如果同时在main.ts
和app.module.ts
中注册了相同的过滤器,全局注册的过滤器将具有更高的优先级,即会覆盖模块级注册的过滤器。
2.1 捕获异常
为了捕获每一个未处理的异常(不管异常类型如何),将 @Catch()
装饰器的参数列表设为空,例如 @Catch()
。
以上就是 Nestjs 中抛出异常的方法,包括了基础异常抛出和自定义异常抛出以及异常处理器,感谢阅读!!!
转载自:https://juejin.cn/post/7383029698115485747