Nest:动态和全局模块

Nest.js 是一个高度模块化的框架,它鼓励使用模块(Module)来组织代码,以实现不同功能区块的隔离。

模块封装最佳建议:

  • 单一职责原则:每个模块应该只关注一个功能和任务。
  • 封装:模块内部的实现应该对外界隐藏,只通过 exports 露出必要的部分给外界使用。
  • 配置与环境隔离:使用配置模块或服务来处理不同环境(开发、测试、生产)的配置。这有助于将配置管理从业务逻辑中解耦。

模块相互配合

导出 PersonService 以便其他模块使用:

导入 PersonModule 以使用它的 PersonService:

在 AppController 就可以使用导入的PersonMoudle 的 PersonService,以及自身 providers 数组的 AppService:

模块重导出

有时候我们希望在导出一个模块的同时,也重新导出它所导入的模块。这样可以让这个模块的消费者直接使用它依赖的模块的功能,而无需显式地导入它们。

在 Nest.js 中,可以使用 exports 数组来重导出模块:

typescript 复制代码
// email.module.ts
@Module({
  imports: [CommonModule],
  providers: [EmailService],
  exports: [EmailService, CommonModule] // 重导出 CommonModule
})
export class EmailModule {}

在上面的代码中,EmailModule 不仅导出了它自己的 EmailService,也重导出了它导入的 CommonModule

这意味着导入 EmailModule 的模块也会自动导入 CommonModule,并可以使用其提供的服务。

这种重导出机制在组织大型应用程序时非常有用,因为它可以减少模块间的耦合,同时简化外部模块的导入过程。

全局模块

全局模块AuthModule 被设置为全局模块,它的 AuthService 可以在应用中的任何地方使用,而无需显式导入 AuthModule

使用 @Global 声明成全局模块并 export 想导出的 Service。

typescript 复制代码
import { Module } from '@nestjs/common';
import { AuthModule } from './auth/auth.module';

@Module({
  imports: [AuthModule],
  // ...其他配置
})
export class AppModule {}

一旦 AuthModule 被导入到根模块,它内部导出的模块就可以直接在其他模块使用,其他不用 imports 其 Module 便可使用其 service。

全局模块通常用于那些提供跨应用程序共享的基础服务的功能,例如配置服务、数据库服务或任何其他需要在多个模块之间共享的服务。

注意:避免过度使用全局模块,代码可读性更好。

动态模块

动态模块允许在模块被导入时动态配置提供者(providers)、控制器(controllers)和导出(exports)。

这种方式非常适合需要根据不同环境或配置动态更改其行为的模块。

新建 Nest 项目:

bash 复制代码
nest new dynamic-module -p npm

创建 CRUD 模块:

bash 复制代码
nest g resource dynamicModule

此时导入的 DynamicModuleModule 内容都是固定:

我们需要导入的时候给其传入一些参数怎么办?

这样写:

多了一个 module 属性指向当前的模块类,即 DynamicModuleModule

我们给 DynamicModuleModule 加一个 register 的静态方法,返回模块定义的对象,外部传入的 options 参数对象会作为一个新的 provider。

导入时配置:

使用 @Inject 注入依赖:

访问 localhost:3000,控制台打印:

这就是动态模块。

上面静态方法 register 方法可以任意取名,但 nest 约定了一些方法名:

  • register:用一次模块传一次配置
  • forRoot:根模块(AppModule)配置一次,例如数据库连接、核心服务等。
  • forRootAsync:类似于 forRoot,但用于异步配置,允许从异步服务中获取配置信息。它通常接收一个 useFactory 这个返回配置对象的工厂函数。
  • forFeature:用 forRoot 固定整体模块,用于局部的时候,可能需要再传一些配置。比如用 forRoot 指定了数据库链接信息,再用 forFeature 指定某个模块访问哪个数据库和表。
  • forFeatureAsync: 类似于 forFeature,但用于异步配置特定功能。

异步动态模块

如果需要异步地提供配置,可以使用 forRootAsync 方法。

这个方法通常与工厂函数或类一起使用,以便异步地解析配置数据,然后再创建模块:

typescript 复制代码
@Module({})
export class DynamicModule {
  static forRootAsync(options: DynamicModuleAsyncOptions): DynamicModule {
    return {
      module: DynamicModule,
      imports: options.imports || [],
      providers: [
        {
          provide: 'CONFIG_OPTIONS',
          useFactory: options.useFactory,
          inject: options.inject || [],
        },
        DynamicService,
      ],
      exports: [DynamicService],
    };
  }
}

在这个异步版本中,useFactory 是一个工厂函数,它可以异步地返回配置对象。
inject 属性是一个数组,它定义了工厂函数的依赖项,这些依赖项将被注入到工厂函数中。

相关推荐
糕冷小美n18 小时前
elementuivue2表格不覆盖整个表格添加固定属性
前端·javascript·elementui
小哥不太逍遥18 小时前
Technical Report 2024
java·服务器·前端
沐墨染18 小时前
黑词分析与可疑对话挖掘组件的设计与实现
前端·elementui·数据挖掘·数据分析·vue·visual studio code
anOnion18 小时前
构建无障碍组件之Disclosure Pattern
前端·html·交互设计
threerocks18 小时前
前端将死,Agent 永生
前端·人工智能·ai编程
苍何18 小时前
即梦Seedance2.0海外火爆出圈,AI 视频的 DeepSeek 时刻来了!(附实测教程)
后端
苍何18 小时前
阿里卷麻了,千问 Qwen-Image-2.0 发布,超强文字渲染、信息图、PPT 轻松做(附实测提示词)
后端
苍何18 小时前
被马斯克疯狂点赞的国产 AI,很可能是 AI 时代的抖音!
后端
苍何19 小时前
国产Windows 版 Claude Cowork 来了,内置海量 Skills,绝了。
后端
问道飞鱼19 小时前
【前端知识】Vite用法从入门到实战
前端·vite·项目构建