生命周期事件 Lifecycle Events

Nest 应用程序以及每个应用程序元素都具有由 Nest 管理的生命周期。Nest 提供**生命周期钩子**,可让您查看关键生命周期事件,并能够在这些事件发生时采取行动(在模块、提供程序或控制器上运行已注册的代码)。

生命周期序列

下图描述了关键应用程序生命周期事件的序列,从应用程序启动到节点进程退出。我们可以将整个生命周期分为三个阶段:初始化运行终止。使用此生命周期,您可以规划模块和服务的适当初始化、管理活动连接,并在应用程序收到终止信号时正常关闭应用程序。

img

生命周期事件

生命周期事件发生在应用程序启动和关闭期间。 Nest 会在以下每个生命周期事件中调用模块、提供程序和控制器上已注册的生命周期钩子方法(需要先启用关闭钩子,如下所述)。如上图所示,Nest 还会调用适当的底层方法来开始监听连接,以及停止监听连接。

在下表中,只有当您明确调用 app.close() 或进程收到特殊系统信号(如 SIGTERM)并且您在应用程序引导时正确调用了 enableShutdownHooks 时,才会触发 onModuleDestroybeforeApplicationShutdownonApplicationShutdown(请参阅下面的应用程序关闭部分)。

生命周期钩子方法触发钩子方法调用的生命周期事件
onModuleInit()主机模块的依赖关系解析后调用。
onApplicationBootstrap()所有模块初始化后调用,但在监听连接之前。
onModuleDestroy()*收到终止信号(例如 SIGTERM)后调用。
beforeApplicationShutdown()*所有 onModuleDestroy() 处理程序完成(Promises 解析或拒绝)后调用;
一旦完成(Promises 解析或拒绝),所有现有连接都将关闭(调用 app.close())。
onApplicationShutdown()*连接关闭后调用(app.close() 解析)。

* 对于这些事件,如果您没有明确调用 app.close(),则必须选择让它们与 SIGTERM 等系统信号一起工作。请参阅下面的 应用程序关闭

警告

上面列出的生命周期钩子不会为 请求范围 类触发。请求范围的类与应用程序生命周期无关,其生命周期不可预测。它们是为每个请求专门创建的,并在发送响应后自动进行垃圾回收。

提示

onModuleInit()onApplicationBootstrap() 的执行顺序直接取决于模块导入的顺序,等待上一个钩子。

用法

每个生命周期钩子都由一个接口表示。从技术上讲,接口是可选的,因为它们在 TypeScript 编译后不存在。尽管如此,使用它们以从强类型和编辑器工具中获益是一种很好的做法。要注册生命周期钩子,请实现相应的接口。例如,要注册在特定类(例如 Controller、Provider 或 Module)的模块初始化期间调用的方法,请通过提供 onModuleInit() 方法实现 OnModuleInit 接口,如下所示:

ts
TS
ts
import { Injectable, OnModuleInit } from '@nestjs/common'

@Injectable()
export class UsersService implements OnModuleInit {
  onModuleInit() {
    console.log(`The module has been initialized.`)
  }
}

异步初始化

OnModuleInitOnApplicationBootstrap 钩子都允许您推迟应用程序初始化过程(返回一个 Promise 或将方法标记为 async 并在方法主体中 await 异步方法完成)。

ts
TS
ts
async onModuleInit(): Promise<void> {
  await this.fetch();
}

应用程序关闭

onModuleDestroy()beforeApplicationShutdown()onApplicationShutdown() 钩子在终止阶段被调用(响应对 app.close() 的显式调用或收到系统信号(如 SIGTERM,如果选择加入)时)。此功能通常与 Kubernetes 一起使用,以管理容器的生命周期,由 Heroku 用于 dynos 或类似服务。

关闭钩子侦听器会消耗系统资源,因此默认情况下它们处于禁用状态。要使用关闭钩子,您必须通过调用 enableShutdownHooks() 来启用侦听器:

ts
import { NestFactory } from '@nestjs/core'
import { AppModule } from './app.module'

async function bootstrap() {
  const app = await NestFactory.create(AppModule)

  // Starts listening for shutdown hooks
  app.enableShutdownHooks()

  await app.listen(3000)
}
bootstrap()
warning

由于固有的平台限制,NestJS 对 Windows 上的应用程序关闭挂钩的支持有限。您可以预期 SIGINT 以及 SIGBREAK 和某种程度上的 SIGHUP 都可以工作 - 阅读更多。但是 SIGTERM 永远不会在 Windows 上工作,因为在任务管理器中终止进程是无条件的,即,应用程序无法检测或阻止它。这里有一些来自 libuv 的 相关文档,可以了解有关如何在 Windows 上处理 SIGINTSIGBREAK 和其他内容的更多信息。另请参阅 Node.js 文档中的 进程信号事件

Info

enableShutdownHooks 通过启动侦听器来消耗内存。如果您在单个 Node 进程中运行多个 Nest 应用(例如,使用 Jest 运行并行测试时),Node 可能会抱怨侦听器进程过多。因此,默认情况下不启用 enableShutdownHooks。当您在单个 Node 进程中运行多个实例时,请注意这种情况。

当应用程序收到终止信号时,它将调用任何已注册的 onModuleDestroy()beforeApplicationShutdown(),然后 onApplicationShutdown() 方法(按上述顺序),并将相应的信号作为第一个参数。如果注册的函数等待异步调用(返回承诺),则 Nest 将不会继续执行该序列,直到承诺被解决或被拒绝。

ts
TS
ts
@Injectable()
class UsersService implements OnApplicationShutdown {
  onApplicationShutdown(signal: string) {
    console.log(signal) // e.g. "SIGINT"
  }
}
Info

调用 app.close() 不会终止 Node 进程,而只会触发 onModuleDestroy()onApplicationShutdown() 钩子,因此如果存在某些间隔、长时间运行的后台任务等,进程不会自动终止。