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

相关推荐
学不会•2 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
活宝小娜4 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点4 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow4 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o4 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic5 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā5 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
qq_17448285756 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
锅包肉的九珍6 小时前
Scala的Array数组
开发语言·后端·scala
心仪悦悦6 小时前
Scala的Array(2)
开发语言·后端·scala