首页 > 解决方案 > NestJS - 如何使用不同的配置多次注册动态模块提供程序?

问题描述

我有一个 knex 模块,它是这样实现的:

import { DynamicModule, Module } from '@nestjs/common';
import { Knex, knex } from 'knex';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import { Logger } from 'winston';

export const KNEX_MODULE = 'KNEX_MODULE';

@Module({})
export class KnexModule {
  static register(options: Knex.Config): DynamicModule {
    return {
      module: KnexModule,
      providers: [
        {
          inject: [WINSTON_MODULE_PROVIDER],
          provide: KNEX_MODULE,
          useFactory: (logger: Logger) => {
            logger.info('Creating new knex instance', {
              context: KnexModule.name,
              tags: ['instance', 'knex', 'create'],
            });
            return knex(options);
          },
        },
      ],
      exports: [KNEX_MODULE],
    };
  }
}

我的应用程序需要访问多个数据库,我知道我可以通过创建多个 knex 实例来做到这一点。所以我尝试两次注册模块,传递不同的配置。但是,该模块只注册了一次。第二个注册调用似乎是重用现有对象而不是创建一个新的 knex 实例。

根据传递的配置,生成多个提供程序的正确方法是什么?我发现最接近的是 typeORM 和 Sequelize 中的 forFeature 函数

标签: node.jstypescriptnestjs

解决方案


我刚刚找到了解决方案。我想错了。我需要在我的模块中注册两个提供程序。不创建我的模块的两个实例。我通过向我的模块添加一个参数来解决它,即提供者令牌。现在它正确地创建了两个提供者。

import { DynamicModule, Module } from '@nestjs/common';
import { Knex, knex } from 'knex';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import { Logger } from 'winston';

export const KNEX_MODULE = 'KNEX_MODULE';

@Module({})
export class KnexModule {
  static register(token: string, options: Knex.Config): DynamicModule {
    return {
      module: KnexModule,
      providers: [
        {
          inject: [WINSTON_MODULE_PROVIDER],
          provide: token,
          useFactory: (logger: Logger) => {
            logger.info('Creating new knex instance', {
              context: KnexModule.name,
              tags: ['instance', 'knex', 'create'],
            });
            return knex(options);
          },
        },
      ],
      exports: [token],
    };
  }
}

每当我想使用它时,我都会像这样注册它:

@Module({
  imports: [KnexModule.register(CatRepository.KNEX_TOKEN, knexConfigs)],
  providers: [CatRepository, CatService],
  controllers: [CatController],
  exports: [CatService],
})
export class CatModule {}

然后在存储库中,我可以注入 cat 数据库的 knex 实例。

@Injectable()
export class CatRepository implements Repository<Cat> {
  // eslint-disable-next-line no-useless-constructor
  public static KNEX_TOKEN = 'KNEX_CATS_TOKEN';

  // eslint-disable-next-line no-useless-constructor
  constructor(
    @Inject(CatRepository.KNEX_TOKEN)
    protected knex: Knex,
  ) {}

  ...
}

推荐阅读