请求生命周期

Nest 应用程序处理请求并按照我们所说的 请求生命周期 的顺序产生响应。使用中间件、管道、守卫和拦截器,在请求生命周期种追踪特定代码的执行位置可能会很困难,特别是当全局、控制器级和路由级组件开始发挥作用时。通常,一个请求通过中间件流到守卫,然后到拦截器,然后到管道,最后返回到返回路径上的拦截器(在生成响应时)。

Middleware(中间件)

中间件按特定顺序执行。首先,Nest 运行全局绑定的中间件(例如绑定的中间件),然后运行模块绑定的中间件,这些中间件是在路径上确定的 app.use 。中间件按照绑定的顺序按顺序运行,类似于 Express 中的中间件工作方式。对于跨不同模块绑定的中间件,绑定到根模块的中间件将首先运行,然后中间件将按照模块添加到 imports 数组的顺序运行。

Guards(守卫)

防护执行从全局防护开始,然后到控制器防护,最后到路由防护。与中间件一样,守卫按绑定顺序运行。例如:

1
2
3
4
5
6
7
8
9
10
11
12
@UseGuards(Guard1, Guard2)
@Controller('cats')
export class CatsController {
constructor(private catsService: CatsService) {}

@UseGuards(Guard3)
@Get()
getCats(): Cats[] {
return this.catsService.getCats();
}
}

Guard1 将在之前 Guard2 执行,并且两者都将在 Guard3 之前执行。

当谈到全局绑定与控制器或本地绑定时,区别在于保护(或其他组件)的绑定位置。

如果通过模块使用 app.useGlobalGuard() 或提供组件,则该组件是全局绑定的。否则,如果装饰器位于控制器类之前,则它绑定到控制器,如果装饰器继续进行路由声明,则绑定到路由。

Interceptors(拦截器)

在大多数情况下,拦截器遵循与守卫相同的模式,但有一个问题:当拦截器返回 RxJS Observables 时,可观察对象将以先进后出的方式解析。因此,入站请求将经过标准的全局、控制器、路由级解析,但请求的响应端(即从控制器方法处理程序返回后)将从路由到控制器再到全局进行解析。此外,管道、控制器或服务引发的任何错误都可以在拦截器的 catchError 运算符中读取。

Pipes(管道)

管道遵循标准的全局到控制器来路由绑定序列,在 @usePipes() 参数方面具有相同的先进先出顺序。但是,在路由参数级别,如果有多个管道在运行,则它们将按照最后一个参数的顺序运行,管道将运行到第一个参数。这也适用于路由级别和控制器级别管道。例如,如果我们有以下控制器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@UsePipes(GeneralValidationPipe)
@Controller('cats')
export class CatsController {
constructor(private catsService: CatsService) {}

@UsePipes(RouteSpecificPipe)
@Patch(':id')
updateCat(
@Body() body: UpdateCatDTO,
@Param() params: UpdateCatParams,
@Query() query: UpdateCatQuery,
) {
return this.catsService.updateCat(body, params, query);
}
}

然后 将 GeneralValidationPipe 运行 ,然后是 ,然后是 body 对象,然后移动到 RouteSpecificPipe query params ,遵循相同的顺序。如果有任何特定于参数的管道,它们将在控制器和路由级别管道之后运行(同样,从最后一个参数到第一个参数)。

Filters(过滤器)

筛选器是唯一不首先解析全局的组件。相反,过滤器从尽可能低的级别解析,这意味着执行从任何路由绑定过滤器开始,然后继续到控制器级别,最后到全局过滤器。请注意,异常不能从一个过滤器传递到另一个过滤器;如果路由级筛选器捕获异常,则控制器或全局级筛选器无法捕获相同的异常。实现此类效果的唯一方法是在筛选器之间使用继承。

仅当在请求过程中发生任何未捕获的异常时,才会执行筛选器。

捕获的异常(例如使用 捕获的 try/catch 异常)不会触发异常筛选器触发。一旦遇到未捕获的异常,生命周期的其余部分将被忽略,请求将直接跳到筛选器。

总结

通常,请求的生命周期看起来如下所示:

1.传入请求
2.在全局范围内绑定的中间件
3.模块绑定中间件
4.全局警卫
5.控制器警卫
6.警卫路由
7.全局拦截器(零部件)
8.控制器拦截器(零部件)
9.路由拦截器(零部件)
10.全局管道
11.控制器的管道
12.路由管道
13.路由参数管道
14.控制器(方法处理程序)
15.服务(如果存在)
16.路由拦截器(post 请求)
17.控制器拦截器(post 请求)
18.全局拦截器(post 请求)
19.异常过滤器(路由,然后是控制器,然后是全局)
20.服务器响应