Skip to content

NestJs Module

nestjs @Module 是一个装饰器, 接收一个对象作为参数, 该对象包含以下四个字段

  1. providers

providers 是使用最频繁地一个字段, 当一个 provider 需要 export时也需要在这里定义, 有多种方式可以生成 provider, 在这里简单介绍一下

  • 使用 @Injectable() 装饰器修饰的类
js
@Injectable()
export class UserService {}
  • 使用 useValue
js
const provider = {
  provide: "name",
  useValue: () => {
    return new Redis({});
  },
};
  • 使用 useFactory
js
const provider = {
  provide: "name",
  useFactory: () => {
    return new Redis({});
  },
};

useFactory 比 useValue 优势在于可以异步处理, 也可以注入依赖对象, 比如注入 configService

js
const provider = {
  provide: 'name',
  useFactory: async(configService: ConfigService) => {
    return new Redis({
      host: configService.get('host'),
    });
  },
  inject: [ConfigService]
};

例子中 async 修饰符不是必须的

  1. imports

imports 用来引入依赖的 module, 如果存在循环依赖也是在这里解决, 下面几种 module 的写法可以被引入

  • 被 @Module 修饰的类
js
// 定义 RedisModule
@Module({
  providers: [
    {
      provide: "redis",
      useValue: () => {
        return new Redis();
      },
    },
  ],
  exports: ["redis"],
})
export class RedisModule {}

// 在 AppModule 中使用 RedisModule
@Module({
  imports: [RedisModule],
})
export class AppModule {}

导入 RedisModule 的目的是为了使用 redis provider, 这里需要分清楚主次.

  • 动态 Module

动态 module 也需要被 @Module 修饰, 根本上也是一个 class, 它的好处是可以在调用时增加参数

js
// 定义 RedisModule
@Module({})
export class RedisModule {
    static forRoot(options: {isGlobal: boolean}): DynamicModule {
      const redis: Provider = {
          provide: 'redis',
          useFactory: (redisService: RedisService) => {
              return redisService.getRedis();
          },
          inject: [ RedisService ],
      };
        return {
            module: RedisModule,
            providers: [RedisService, redis],
            exports: [redis],
        };
    }
}
// 在 AppModule 中使用 RedisModule
@Module({
  imports: [RedisModule.forRoot()],
})
export class AppModule {}

其中 forRoot 名称是一个约定俗成的静态方法, 你可以随意修改方法名, 但是不推荐

  • forwardRef() 解决循环依赖

当 redisModule 跟 AppModule 互相依赖, 需要有一方使用 forwardRef, 用来解决循环依赖问题, 这个方法也可以解决 providers 间的循环依赖

js
@Module({
  imports: [
    forwardRef(() => RedisModule),
  ],
})
export class AppModule {}
  1. exports

exports 导出的是具体的 providers, 它和 providers 配合使用, 同理 imports 导入的也是 exports 的类

  1. controllers

从字面意思就能看出, 它里面定义的都是 controllers, controller 是使用 @Controller() 装饰器修饰的类