NestJS 生命周期事件

2023-09-08 15:16 更新

所有應(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();
}

Application Shutdown

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"
  }
}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號