如何使动态模块成为全局模块?

时间:2019-11-20 06:45:43

标签: nestjs

在我的应用程序中,我想在整个项目中使用一个服务类实例。服务类将由动态模块初始化。

详细信息

我有一个名为LoggerModule的模块,该模块具有静态功能寄存器。我们使用此方法在应用模块Eg:LoggerModule.register(options)中进行初始化。在register方法中,我们将返回一个动态模块,它将将此选项设置为自定义提供程序。 例如:

return {
      module: LoggerModule,
      providers: [
        {
          provide: CONFIG_OPTIONS,
          useValue: options,
        },
        LoggerService,
      ],
      exports: [LoggerService],
    };

在这里,我们有一个LoggerService注入CONFIG_OPTIONS,以便我们可以使用服务类来获取选项。现在,我希望能够通过在类中注入服务来从项目中的任何位置访问该服务,但是由于该模块不是全局的,因此当前我必须在我正在使用的所有模块中包括LoggerModule.register()。我尝试使用@Global()批注,但似乎不起作用。

您能建议有关此操作的任何方法吗?如果是,请给我分享一个例子吗?

1 个答案:

答案 0 :(得分:0)

要使动态模块全局化,您需要做的就是在@Global()装饰器上方添加@Module()装饰器。与您正在使用的任何其他模块相同。 https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html


编辑11/22/19

好吧,我试图尽可能地模仿您的设置,并提供给我的东西以及我仍然在本地机器上躺着的东西。我能够使用以下设置获得一个全局模块:

配置模块(将是全局模块)

import { DynamicModule, Module, Provider, Global } from '@nestjs/common';
import { CONFIG_MODULE_OPTIONS } from './config.constants';
import { createConfigProvider } from './config.provider';
import { ConfigService } from './config.service';
import {
  ConfigModuleAsyncOptions,
  ConfigModuleOptions,
  ConfigOptionsFactory,
} from './interfaces/config-options.interface';

@Global()
@Module({})
export class ConfigModule {
  static forRoot(options: ConfigModuleOptions): DynamicModule {
    return {
      module: ConfigModule,
      providers: [ConfigService, ...createConfigProvider(options)],
      exports: [ConfigService],
    };
  }

  static forRootAsync(options: ConfigModuleAsyncOptions): DynamicModule {
    return {
      module: ConfigModule,
      imports: options.imports || [],
      providers: [ConfigService, ...this.createAsyncProviders(options)],
      exports: [ConfigService],
    };
  }

  private static createAsyncProviders(
    options: ConfigModuleAsyncOptions,
  ): Provider[] {
    if (options.useExisting || options.useFactory) {
      return [this.createAsyncOptionsProviders(options)];
    }
    if (options.useClass) {
      return [
        this.createAsyncOptionsProviders(options),
        {
          provide: options.useClass,
          useClass: options.useClass,
        },
      ];
    }
    throw new Error('Invalid ConfigModule configuration.');
  }

  private static createAsyncOptionsProviders(
    options: ConfigModuleAsyncOptions,
  ): Provider {
    if (options.useFactory) {
      return {
        provide: CONFIG_MODULE_OPTIONS,
        useFactory: options.useFactory,
        inject: options.inject || [],
      };
    }
    return {
      provide: CONFIG_MODULE_OPTIONS,
      useFactory: async (optionsFactory: ConfigOptionsFactory) =>
        await optionsFactory.createConfigOptions(),
      inject: [options.useExisting || options.useClass || ''],
    };
  }
}

我为完全可重用的Nest模块进行了此设置,但由于那里已经有一些配置模块,因此便废弃了这个想法。

动态模块(是的,我知道拼写错误)

import { Module } from '@nestjs/common';
import { DyanmicTestService } from './dyanmic-test.service';
import { DyanmicTestController } from './dyanmic-test.controller';

@Module({
  providers: [DyanmicTestService],
  controllers: [DyanmicTestController],
})
export class DyanmicTestModule {}

Dyanmic服务将注入配置服务,但请注意,我们此处未导入配置模块。这是因为它是全局的,并且一旦在App Module中注册,就无需将其导入其他任何地方。

应用模块

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DyanmicTestModule } from './dyanmic-test/dyanmic-test.module';
import { ConfigModule } from './config/config.module';

@Module({
  imports: [
    ConfigModule.forRootAsync({
      useFactory: () => ({
        fileName: '.env',
        useProcess: false,
      }),
    }),
    DyanmicTestModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

所有这些代码Here are the docs on it