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

相关推荐
桂月二二4 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
Ai 编码助手5 小时前
在 Go 语言中如何高效地处理集合
开发语言·后端·golang
小丁爱养花5 小时前
Spring MVC:HTTP 请求的参数传递2.0
java·后端·spring
Channing Lewis5 小时前
什么是 Flask 的蓝图(Blueprint)
后端·python·flask
hunter2062065 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb5 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角5 小时前
CSS 颜色
前端·css
浪浪山小白兔6 小时前
HTML5 新表单属性详解
前端·html·html5
轩辕烨瑾7 小时前
C#语言的区块链
开发语言·后端·golang
lee5767 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm