Nest.js 生命周期事件
所有应用程序元素都有一个由 Nest 管理的生命周期。Nest 提供了生命周期钩子,提供了对关键生命时刻的可见性,以及在关键时刻发生时采取行动(在你的module,injectable或者controller中注册代码)的能力。
生命周期事件
生命周期事件在应用初始化与终止时发生。Nest在 modules
,injectables
和 controllers
的以下每个生命周期事件(首先要使能shutdown钩子,如下描述)中调用注册钩子方法。和上图所示的一样,Nest也调用合适的底层方法来监听连接,以及终止监听连接。
在下述表格中,onModuleDestroy
, beforeApplicationShutdown
和 onApplicationShutdown
仅仅在显式调用 app.close()
或者应用收到特定系统信号(例如 SIGTERM)并且在初始化时(参见下表的应用shutdown部分)正确调用了enableShutdownHooks方法后被触发。
生命周期钩子方法 | 生命周期时间触发钩子方法调用 |
---|---|
OnModuleInit() | 初始化主模块依赖处理后调用一次 |
OnApplicationBootstrap() | 在应用程序完全启动并监听连接后调用一次 |
OnModuleDestroy() | 收到终止信号(例如SIGTERM)后调用 |
beforeApplicationShutdown() | 在onModuleDestroy()完成(Promise被resolved或者rejected);一旦完成,将关闭所有连接(调用app.close() 方法). |
OnApplicationShutdown() | 连接关闭处理时调用(app.close()) |
上述列出的生命周期钩子没有被请求范围类触发。请求范围类并没有和生命周期以及不可预测的寿命绑定。他们为每个请求单独创建,并在响应发送后通过垃圾清理系统自动清理。
用例
所有应用周期的钩子都有接口表示,接口在技术上是可选的,因为它们在 TypeScript 编译之后就不存在了。尽管如此,为了从强类型和编辑器工具中获益,使用它们是一个很好的实践。要使用合适的接口。例如,要注册一个方法在特定类(例如,控制器,提供者或者模块)初始化时调用,使用OnModuleInit接口,提供onModuleInit()方法,如下:
import { Injectable, OnModuleInit } from '@nestjs/common';
@Injectable()
export class UsersService implements OnModuleInit {
onModuleInit() {
console.log(`The module has been initialized.`);
}
}
异步初始化
此外,OnModuleInit
和 OnApplicationBootstrap
钩子都允许您延迟应用程序初始化过程(返回一个Promise或在方法主体中将方法标记为async和await异步方法)。
async onModuleInit(): Promise<void> {
await this.fetch();
}
Application Shutdown
onModuleDestroy()
, beforeApplicationShutdown()
和 onApplicationShutdown()
钩子程序响应系统终止信号(当应用程序通过显示调用app.close()或者收到SIGTERM系统信号时),以优雅地关闭 Nest 应用程序。这一功能通常用于 Kubernetes 、Heroku 或类似的服务。
系统关闭钩子消耗系统资源,因此默认是禁用的。要使用此钩子,必须通过enableShutdownHooks()激活侦听器。
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();
警告
⚠️ : 由于平台限制,NestJs的关闭钩子在Windows下有一些限制。SIGINT,SIGBREAK以及一些SIGHUP信号可以工作–阅读更多。然而,SIGTERM在Windows下不工作,因为在任务管理器中关闭一个线程是无条件的。“例如,应用没有办法发现或者阻止它”。一些Windows下关于SIGINT和SIGBREAK的libuv的相关文档。参见Nodejs的线程信号事件文档。
提示
:enableShutdownHooks开始监听时消耗内存。如果要在一个单独Node线程中运行多个Nest应用(例如,使用多个Jest运行测试),Node会抱怨监听者太多。出于这个原因,enableShutdownHooks默认未启用。要在单个Node进程中运行多个实例时尤其要注意这一点。
如果应用程序接收到一个终止信号,它将会依次调用注册的onModuleDestroy(), beforeApplicationShutdown()和onApplicationShutdown()方法,将响应信号作为第一个参数。如果一个注册函数等待异步调用(作为promise),那么在 promise 被解析或拒绝之前,它不会关闭 Nest 应用程序。
@Injectable()
class UsersService implements OnApplicationShutdown {
onApplicationShutdown(signal: string) {
console.log(signal); // e.g. "SIGINT"
}
}