NestJS 生命周期详解
引言
NestJS 是一个基于 Node.js 的渐进式 Web 应用框架,它采用了模块化、依赖注入等设计模式,极大地提升了开发效率和代码可维护性。了解 NestJS 的生命周期对于开发者来说至关重要,因为它可以帮助我们更好地理解应用的启动、运行和关闭过程,从而在合适的时机执行特定的操作,如资源初始化、数据清理等。本文将详细介绍 NestJS 的生命周期钩子及其使用场景。
NestJS 生命周期概述
NestJS 的生命周期可以分为三个主要阶段:应用启动阶段、运行阶段和应用关闭阶段。每个阶段都有相应的生命周期钩子函数,开发者可以通过实现这些钩子函数来执行自定义逻辑。
应用启动阶段
在应用启动阶段,NestJS 会完成一系列的初始化工作,包括模块解析、依赖注入、控制器和服务实例化等。以下是该阶段的主要生命周期钩子:
1. OnModuleInit
- 接口定义:
OnModuleInit
接口只有一个方法onModuleInit()
,当模块初始化完成后,该方法会被调用。 - 使用场景:常用于模块级别的初始化操作,如连接数据库、加载配置文件等。
- 示例代码:
import { Module, OnModuleInit } from '@nestjs/common';
@Module({})
export class AppModule implements OnModuleInit {
onModuleInit() {
console.log('AppModule 初始化完成');
// 可以在这里进行数据库连接等操作
}
}
2. OnApplicationBootstrap
- 接口定义:
OnApplicationBootstrap
接口的onApplicationBootstrap()
方法会在整个应用启动完成后被调用。 - 使用场景:适用于需要在所有模块初始化完成后执行的操作,如启动定时任务、注册全局事件监听器等。
- 示例代码:
import { Module, OnApplicationBootstrap } from '@nestjs/common';
@Module({})
export class AppModule implements OnApplicationBootstrap {
onApplicationBootstrap() {
console.log('应用启动完成');
// 启动定时任务
setInterval(() => {
console.log('定时任务执行');
}, 5000);
}
}
运行阶段
在应用运行阶段,NestJS 主要处理 HTTP 请求和响应。虽然这个阶段没有像启动和关闭阶段那样明确的生命周期钩子,但可以通过中间件、拦截器、守卫等机制来处理请求和响应的各个环节。
1. 中间件
- 作用:中间件是在路由处理程序之前执行的函数,用于处理请求和响应,如日志记录、身份验证等。
- 示例代码:
import { Request, Response, NextFunction } from 'express';
export function loggerMiddleware(req: Request, res: Response, next: NextFunction) {
console.log(`收到 ${req.method} 请求: ${req.url}`);
next();
}
在模块中使用中间件:
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { loggerMiddleware } from './logger.middleware';
@Module({})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(loggerMiddleware)
.forRoutes('*');
}
}
2. 拦截器
- 作用:拦截器可以在请求处理前后执行额外的逻辑,如转换响应数据、缓存请求等。
- 示例代码:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable()
export class TransformInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
map(data => ({
status: 'success',
data,
})),
);
}
}
在控制器中使用拦截器:
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { TransformInterceptor } from './transform.interceptor';
@Controller()
@UseInterceptors(TransformInterceptor)
export class AppController {
@Get()
getHello(): string {
return 'Hello World!';
}
}
应用关闭阶段
当应用需要关闭时,NestJS 提供了相应的生命周期钩子来执行清理操作,如关闭数据库连接、释放资源等。
1. OnModuleDestroy
- 接口定义:
OnModuleDestroy
接口的onModuleDestroy()
方法会在模块销毁之前被调用。 - 使用场景:用于模块级别的资源清理,如关闭数据库连接池、停止子进程等。
- 示例代码:
import { Module, OnModuleDestroy } from '@nestjs/common';
import { Connection } from 'typeorm';
@Module({})
export class AppModule implements OnModuleDestroy {
constructor(private readonly connection: Connection) {}
async onModuleDestroy() {
console.log('AppModule 即将销毁');
await this.connection.close();
}
}
2. BeforeApplicationShutdown
和 OnApplicationShutdown
- 接口定义:
BeforeApplicationShutdown
接口的beforeApplicationShutdown(signal?: string)
方法会在应用关闭之前被调用,OnApplicationShutdown
接口的onApplicationShutdown(signal?: string)
方法会在应用关闭时被调用。 - 使用场景:
beforeApplicationShutdown
可用于执行一些准备工作,如停止接收新的请求;onApplicationShutdown
用于执行最终的清理操作,如释放所有资源。 - 示例代码:
import { Module, BeforeApplicationShutdown, OnApplicationShutdown } from '@nestjs/common';
@Module({})
export class AppModule implements BeforeApplicationShutdown, OnApplicationShutdown {
beforeApplicationShutdown(signal: string) {
console.log(`应用即将关闭,信号: ${signal}`);
// 停止接收新的请求
}
onApplicationShutdown(signal: string) {
console.log(`应用已关闭,信号: ${signal}`);
// 释放所有资源
}
}
总结
NestJS 的生命周期钩子为开发者提供了强大的控制能力,使得我们可以在应用的不同阶段执行自定义逻辑。通过合理使用这些钩子,我们可以确保应用的稳定性和可靠性,同时提高代码的可维护性和可扩展性。在实际开发中,我们应该根据具体的需求选择合适的生命周期钩子,并在其中实现相应的功能。