在 NestJS 中,控制流指的是请求从进入应用到最终返回响应的整个过程。管道、拦截器、守卫、中间件和异常过滤器在这一过程中扮演不同的角色,它们分别在不同的阶段进行处理。
控制流的执行顺序
在一个典型的 NestJS 请求生命周期中,各个组件的执行顺序如下:
-
中间件 (Middleware)
- 执行时机:请求进入应用后,路由处理之前。
- 作用:中间件是请求生命周期中的第一个环节,它可以用来做一些全局性的操作,如日志记录、认证、CORS、请求体解析等。
- 执行顺序:可以在
main.ts
中通过app.use()
按照顺序应用。
-
守卫 (Guards)
- 执行时机:请求到达路由处理器之前,控制器的每个路由方法调用之前。
- 作用:守卫用于 决定 请求是否被允许继续进行,通常用于权限控制、认证等。
- 执行顺序:守卫是在中间件之后执行的,且在管道和拦截器之前执行。
-
管道 (Pipes)
- 执行时机:请求进入控制器的处理方法之前(即方法执行之前)。
- 作用:管道主要用于输入数据的处理,如验证、转换、清洗等。
- 执行顺序:管道在守卫之后执行,它负责处理请求数据并验证是否符合预期。如果验证失败,管道可以抛出异常,阻止请求继续处理。
-
路由处理器 (Handler)
- 执行时机:在守卫和管道之后,实际的控制器方法被调用。
- 作用:处理请求的核心逻辑,通常是从数据库获取数据或执行业务逻辑。
-
拦截器 (Interceptors)
- 执行时机:在路由处理器执行之后,但在响应返回客户端之前。
- 作用:拦截器可以操作返回的数据、执行日志、缓存、异常处理等。它们不仅可以处理输出,还可以执行一些跨切面关注的逻辑。
- 执行顺序:拦截器通常在路由处理器执行之后、响应返回之前执行。
-
异常过滤器 (Exception Filters)
- 执行时机:如果在请求生命周期的任何阶段(如管道、守卫、处理方法等)发生了异常,异常过滤器会捕获并处理这些异常。
- 作用:异常过滤器用于捕获和处理应用中的异常,可以在此处理返回给客户端的错误信息或日志。
执行顺序总结:
- 中间件:请求到达应用时,首先处理的组件(可以修改请求、执行验证等)。
- 守卫:在路由处理器之前,决定是否允许请求继续进行。
- 管道:在守卫通过后,对输入数据进行验证、转换、清洗。
- 路由处理器:处理请求的实际业务逻辑。
- 拦截器:在路由处理器之后、响应返回之前,可以修改响应数据、执行日志等操作。
- 异常过滤器:处理任何阶段发生的异常,提供统一的错误处理机制。
图示化流程
请求 → 中间件 → 守卫 → 管道 → 路由处理器 → 拦截器 → 异常过滤器 → 响应
- 中间件 处于最前面,负责处理全局性的操作。
- 守卫 在管道之前,控制访问的权限。
- 管道 负责验证和处理请求数据。
- 路由处理器 执行实际的业务逻辑。
- 拦截器 对响应数据进行处理(例如修改返回数据)。
- 异常过滤器 捕获并处理过程中出现的异常。
总结:
这些组件各自关注不同的任务,并按顺序执行,从而完成对请求和响应的全面控制。正确理解它们的位置和作用,有助于在应用中更加高效地组织代码和逻辑。