NestJS 生命周期详解

By xuhuan 2025-03-05 07:57:46 文章分类:其它

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. BeforeApplicationShutdownOnApplicationShutdown

  • 接口定义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 的生命周期钩子为开发者提供了强大的控制能力,使得我们可以在应用的不同阶段执行自定义逻辑。通过合理使用这些钩子,我们可以确保应用的稳定性和可靠性,同时提高代码的可维护性和可扩展性。在实际开发中,我们应该根据具体的需求选择合适的生命周期钩子,并在其中实现相应的功能。