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 属性是一个数组,它定义了工厂函数的依赖项,这些依赖项将被注入到工厂函数中。

相关推荐
duanshu_11 分钟前
官网表单与下载异常怎么排查?五个环节定位故障
前端·自动化·flyweight
Zhou14113631 分钟前
SpringBoot_03_Web开发
前端·spring boot·python
辻弋20132 分钟前
【无标题】
大数据·服务器·前端·搜索引擎·开源软件
蜗牛互联网1 小时前
WSL Containers GA:本地AI容器的生命周期、网络与治理验收
java·网络·人工智能·后端
FluxArt1 小时前
GPT Image 2.5 中文提示词教程:Flux Art 可复用模板
前端·gpt·算法
搬砖的小码农_Sky2 小时前
AI Agent:Windows上Node.js安装后 npm -v报错
前端·npm·node.js·人机交互
Zhou1411362 小时前
SpringBoot_02_自动配置原理
java·spring boot·后端
计算机魔术师2 小时前
半年翻倍!OpenAI再融300亿,估值冲到1.4万亿
前端
研☆香3 小时前
jQuery + Swiper.js 实现动态渲染轮播图
前端·javascript·jquery
子兮曰3 小时前
Node.js 50个优势场景盘点:一个人单干,为啥我多数时候只用它
前端·后端