【问题标题】:NestJS - how to use ConfigService outside NestJS managed class?NestJS - 如何在 NestJS 托管类之外使用 ConfigService?
【发布时间】:2020-07-23 23:01:14
【问题描述】:

我正在开发一个 NestJS 项目。这是我的项目结构:

-src
 -config
  -configuration.ts
 -modules
  -auth
  -user
 -utils
  -util.ts

在我的身份验证和用户模块中,我导入 ConfigModule,然后我可以使用 ConfigService 从 configuration.ts 文件中获取配置值。

但是如何在utils/util.ts 文件中获取配置值?
它只是一个包含一些帮助文件的目录,而不是模块目录。

【问题讨论】:

    标签: nestjs


    【解决方案1】:

    假设您希望使用相同的 ConfigService 实例...从 NestJS 的角度来看,我看到两个选项:

    • 将您的 util 函数分组到单个 Provider 中,并将其视为 NestJS 应用程序的合法组件(或按职责将它们分组到多个 Provider 中,这也更有意义)
    • 将您的配置服务作为 node.js 模块提供,您可以从 util“按原样”导入,并从您的 NestJS 应用程序声明为自定义 Provider

    关于第二个选项:

    // regular typescript class
    // exported so you can type your injected "configService" in other classes
    export class ConfigService {
     // your code
    }
    
    export default new ConfigService();
    

    这可以通过util原样导入。
    并通过创建自定义提供程序注入到您的 NestJS 应用程序中:

    import configService, { ConfigService } from './somewhere/config-service.ts';
    
    const configServiceProvider = {
      provide: ConfigService,
      useValue: configService,
    };
    
    // and use it in your ConfigModule
    @Module({ 
      providers: [configServiceProvider],
      exports: [configServiceProvider],
    })
    export class ConfigModule {}
    

    在您的 NestJS 应用程序中注入 ConfigService 时,该值将解析为 configService(显然,只要 ConfigModule 在范围内)。

    但是,这不允许您的ConfigService 在其构造函数参数中注入任何内容...除非您准备好使用ConfigService 的两个不同实例(一个用于util,一个用于您的 NestJS 应用程序)。在这种情况下,您可以使用 Factory 提供程序,如下所示:

    const configServiceProvider = {
      provide: ConfigService,
      useFactory: (somethingService: SomethingService) => new ConfigService(somethingService),
      inject: [SomethingService],
    };
    
    // and in the ConfigModule
    @Module({
      imports: [SomethingModule], // so you can inject SomethingService
      providers: [configServiceProvider],
      exports: [configServiceProvider],
    })
    export class ConfigModule {}
    

    然而这并没有多大意义,因为您还需要在 NestJS 范围内out 提供ConfigService 的依赖项,以便在util 函数中使用它。


    另一种选择(不考虑任何框架)是允许自己在util 中传递(通过参数)ConfigService... 例如:

    // old version
    export const readDeploymentConfigFile = (filePath: string) => {
      // ...
    };
    
    // new version
    export const readDeploymentConfigFile = (configService: ConfigService) => (filePath: string) => {
      // ...
    };
    

    This video 可能会鼓舞人心(Rúnar Óli Bjarnason 的“Dead-Simple Dependency Injection”,2012 年),即使这与 TypeScript 或 Nest 无关。

    但这并不适合用作 API,而且它还可能暴露出一些设计缺陷...如果您的 util 函数需要一些动态/外部配置值,我们还能将它们视为 util 函数吗?

    【讨论】:

      【解决方案2】:

      当声明一个配置模块时,你可以像这样传递一个对象:

      ConfigModule.forRoot({
        envFilePath: ['.env'],
        isGlobal: true,
        load: [config],
      }),
      

      此加载参数是返回 javascript 对象的函数列表,然后将其添加到您的配置中,然后您可以使用 ConfigService 来获取您的配置:

      ConfigService.get("NODE_ENV") //This gets a configuration loaded from .env file
      
      ConfigService.get("mongoose.connectionOptions") //This is a config you setted in app.config.ts for example and return an object containing mongoose connection options
      

      您的配置文件可能如下所示:

      var config = {
        app: {
          environment: process.env.NODE_ENV,
        },
        sentry: {
          dsn: process.env.SENTRY_DSN,
          tracesSampleRate: 1.0,
        },
        rabbit: {
          connection: {
            protocol: process.env.RABBITMQ_PROTOCOL,
            hostname: process.env.RABBITMQ_HOST,
            port: process.env.RABBITMQ_PORT,
            vhost: process.env.RABBITMQ_VHOST,
            username: process.env.RABBITMQ_USERNAME,
            password: process.env.RABBITMQ_PASSWORD,
          },
        },
        mongo: {
          user: process.env.MONGO_USER,
          password: process.env.MONGO_PASS,
          dbName: process.env.MONGO_NAME,
          port: process.env.MONGO_PORT,
          host: process.env.MONGO_HOST,
          connString: `mongodb://${process.env.MONGO_HOST}:${process.env.MONGO_PORT}/${process.env.MONGO_NAME}?authSource=admin`,
        },
        mongooseOptions: {
          useNewUrlParser: true,
          useUnifiedTopology: true,
          useFindAndModify: false,
          user: process.env.MONGO_USER,
          pass: process.env.MONGO_PASS,
          keepAlive: true,
          uri: `mongodb://${process.env.MONGO_HOST}:${process.env.MONGO_PORT}/${process.env.MONGO_NAME}?authSource=admin`,
        },
      };
      
      var {
        protocol,
        username,
        password,
        hostname,
        port,
        vhost,
      } = config.rabbit.connection;
      config.rabbit.connection.connString = `${protocol}://${username}:${password}@${hostname}:${port}/${vhost}`;
      
      export default () => config;
      

      【讨论】:

        猜你喜欢
        • 2021-01-18
        • 2019-03-05
        • 2022-06-17
        • 1970-01-01
        • 1970-01-01
        • 2018-12-01
        • 2022-07-14
        • 1970-01-01
        • 2022-01-02
        相关资源
        最近更新 更多