所有應(yīng)用程序元素都有一個由 Nest 管理的生命周期。Nest 提供了生命周期鉤子,提供了對關(guān)鍵生命時刻的可見性,以及在關(guān)鍵時刻發(fā)生時采取行動(在你的module,injectable或者controller中注冊代碼)的能力。
下圖描述了關(guān)鍵應(yīng)用生命周期事件序列,從應(yīng)用引導(dǎo)之時到node應(yīng)用退出。我們可以把整個生命周期劃分為三個階段:初始化,運行和終止。使用生命周期,你可以合理計劃模塊和服務(wù)的初始化,管理活動鏈接,并且在應(yīng)用程序收到終止指令時優(yōu)雅地退出。
生命周期事件在應(yīng)用初始化與終止時發(fā)生。Nest在modules,injectables和controllers的以下每個生命周期事件(首先要使能shutdown鉤子,如下描述)中調(diào)用注冊鉤子方法。和上圖所示的一樣,Nest也調(diào)用合適的底層方法來監(jiān)聽連接,以及終止監(jiān)聽連接。
在下述表格中,onModuleDestroy, beforeApplicationShutdown和 onApplicationShutdown僅僅在顯式調(diào)用app.close()或者應(yīng)用收到特定系統(tǒng)信號(例如 SIGTERM)并且在初始化時(參見下表的應(yīng)用shutdown部分)正確調(diào)用了enableShutdownHooks方法后被觸發(fā)。
生命周期鉤子方法 | 生命周期時間觸發(fā)鉤子方法調(diào)用 |
---|---|
OnModuleInit() | 初始化主模塊依賴處理后調(diào)用一次 |
OnApplicationBootstrap() | 在應(yīng)用程序完全啟動并監(jiān)聽連接后調(diào)用一次 |
OnModuleDestroy() | 收到終止信號(例如SIGTERM)后調(diào)用 |
beforeApplicationShutdown() | 在onModuleDestroy() 完成(Promise被resolved或者rejected);一旦完成,將關(guān)閉所有連接(調(diào)用app.close() 方法). |
OnApplicationShutdown() | 連接關(guān)閉處理時調(diào)用(app.close()) |
上述列出的生命周期鉤子沒有被請求范圍類觸發(fā)。請求范圍類并沒有和生命周期以及不可預(yù)測的壽命綁定。他們?yōu)槊總€請求單獨創(chuàng)建,并在響應(yīng)發(fā)送后通過垃圾清理系統(tǒng)自動清理。
所有應(yīng)用周期的鉤子都有接口表示,接口在技術(shù)上是可選的,因為它們在 TypeScript 編譯之后就不存在了。盡管如此,為了從強類型和編輯器工具中獲益,使用它們是一個很好的實踐。要使用合適的接口。例如,要注冊一個方法在特定類(例如,控制器,提供者或者模塊)初始化時調(diào)用,使用OnModuleInit接口,提供onModuleInit()方法,如下:
import { Injectable, OnModuleInit } from '@nestjs/common';
@Injectable()
export class UsersService implements OnModuleInit {
onModuleInit() {
console.log(`The module has been initialized.`);
}
}
此外,OnModuleInit 和 OnApplicationBootstrap 鉤子都允許您延遲應(yīng)用程序初始化過程(返回一個Promise或在方法主體中將方法標(biāo)記為async和await異步方法)。
async onModuleInit(): Promise<void> {
await this.fetch();
}
onModuleDestroy(), beforeApplicationShutdown()和 onApplicationShutdown()鉤子程序響應(yīng)系統(tǒng)終止信號(當(dāng)應(yīng)用程序通過顯示調(diào)用app.close()或者收到SIGTERM系統(tǒng)信號時),以優(yōu)雅地關(guān)閉 Nest 應(yīng)用程序。這一功能通常用于 Kubernetes 、Heroku 或類似的服務(wù)。
系統(tǒng)關(guān)閉鉤子消耗系統(tǒng)資源,因此默認(rèn)是禁用的。要使用此鉤子,必須通過enableShutdownHooks()激活偵聽器。
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Starts listening to shutdown hooks
app.enableShutdownHooks();
await app.listen(3000);
}
bootstrap();
由于平臺限制,NestJs的關(guān)閉鉤子在Windows下有一些限制。SIGINT,SIGBREAK以及一些SIGHUP信號可以工作–閱讀更多。然而,SIGTERM在Windows下不工作,因為在任務(wù)管理器中關(guān)閉一個線程是無條件的?!袄?,應(yīng)用沒有辦法發(fā)現(xiàn)或者阻止它”。一些Windows下關(guān)于SIGINT和SIGBREAK的libuv的相關(guān)文檔。參見Nodejs的線程信號事件文檔。
enableShutdownHooks開始監(jiān)聽時消耗內(nèi)存。如果要在一個單獨Node線程中運行多個Nest應(yīng)用(例如,使用多個Jest運行測試),Node會抱怨監(jiān)聽者太多。出于這個原因,enableShutdownHooks默認(rèn)未啟用。要在單個Node進程中運行多個實例時尤其要注意這一點。
如果應(yīng)用程序接收到一個終止信號,它將會依次調(diào)用注冊的onModuleDestroy(), beforeApplicationShutdown()和onApplicationShutdown()方法,將響應(yīng)信號作為第一個參數(shù)。如果一個注冊函數(shù)等待異步調(diào)用(作為promise),那么在 promise 被解析或拒絕之前,它不會關(guān)閉 Nest 應(yīng)用程序。
@Injectable()
class UsersService implements OnApplicationShutdown {
onApplicationShutdown(signal: string) {
console.log(signal); // e.g. "SIGINT"
}
}
更多建議: