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