【问题标题】:NestJs: dynamic module IoC scopeNestJs:动态模块 IoC 范围
【发布时间】:2022-02-05 09:41:05
【问题描述】:
  • 框架如何管理DynamicModules 的生命周期?

The NestJs documentation on Modules states that:

在 Nest 中,模块默认是单例的,因此您可以轻松地在多个模块之间共享任何提供程序的同一个实例。

  • 如何在模块之间共享多个动态模块实例?

The NestJs documentation on DynamicModules states that:

事实上,我们的register() 方法会返回一个DynamicModule。动态模块只不过是在运行时创建的模块,具有与静态模块完全相同的属性,加上一个称为模块的附加属性。

  • 如何管理/更改DynamicModules 的范围?例如,将它们从传递行为更改为单例。定义它们的注入令牌,按需检索它们等。

【问题讨论】:

    标签: nestjs


    【解决方案1】:

    框架如何管理 DynamicModules 的生命周期?

    一般来说,就像它做任何其他模块一样。动态模块只是由函数配置并由对象表示的模块的特殊名称。最终结果通常类似于

    {
      module: SomeModuleClass,
      imports: [Imports, For, The, Module],
      providers: [SomeProviderToken, SomeProviderService, ExtraProvidersNeeded],
      exports: [SomeProviderService],
    }
    

    与您在 @Module() 装饰器中看到的几乎相同,但通过可能使用 DI 而不是直接编写的函数进行配置

    如何在模块之间共享多个动态模块实例?

    我可能需要在这里澄清一下,但是一旦我知道这里的目标是什么,或者你想要做什么,我会很乐意更详细地编辑我的答案。

    您如何管理/更改 DynamicModules 的范围?例如,将它们从传递行为更改为单例。定义它们的注入令牌,按需检索它们等。

    共享您的配置(除了创建模块@Global())最简单的选择是创建一个包装器模块,该模块在配置后重新导出动态模块。

    示例:假设我们有一个动态的FooModule,我们想将application 传递给它,以指定应用程序的名称,并且我们想在其他几个地方重用该模块

    @Module({
      imports: [
        FooModule.forRoot(
          { application: 'StackOverflow Dynamic Module Scope Question' }
        )
      ],
      exports: [FooModule],
    })
    export class FooWrapperModule {}
    

    现在我们不再在多个地方再次导入FooModule.forRoot(),而是导入FooWrapperModule,并获得与最初传递的配置相同的FooService实例。

    我想提一下,按照惯例,DynamicModule.forRoot/Async()通常意味着在RootModule 中进行单次注册,通常有一个@Global()isGlobal: true配置附加到它的某个地方。情况并非总是如此,但它相对正确。

    DynamicModule.register/Async() 另一方面,通常意味着我们正在为这个模块配置一个动态模块仅为这个模块,它可以在别处重新配置以拥有自己的单独配置. This can lead to cool setups where you can have multiple JwtService instances that have different secret values for signing (like for an access and refresh token signing service).

    然后是DynamicModule.forFeature(),它类似于register,因为它是基于每个模块的,但通常它使用来自已经进行的forRoot/Async() 调用的配置。 @nestjs/typeorm 模块、mikro-orm/nestjs 模块和@ogma/nestjs-module 模块是我能想到的三个独立示例,它们遵循这种模式。这是允许在根级别进行一般配置(应用程序名称、数据库连接选项等)然后允许在模块级别进行范围配置(将注入哪些实体、记录器上下文等)的好方法

    【讨论】:

    • "共享您的配置的最简单的选择(除了制作模块@Global())是制作一个包装器模块,该模块在配置后重新导出动态模块。" 但是,如果您将模块包装在“静态模块”中,则无法与在其上下文中不可用的 DynamicModule 共享数据(如下所示)。 @Module({ imports: [ MyLibDynModule.register(some data available in App but not in Lib); ], }) export class AppModule {} 不过,我认为@Global 解决了这个问题。
    • 我不确定我是否遵循。动态模块的想法是可配置的,对吗?如果您想轻松地重用该配置,那么包装模块是一种非常简单的方法,不会损害原始动态模块。如果您需要在一个地方注册一个主配置,并与额外的配置一起重新使用它,forRoot+forFeature 方法听起来就像您需要的那样。 I have a good example of that here
    • 我不明白为什么没有以比包装模块等更简单的方式为 NestJs 开发人员提供模块范围内的更多功能。只需在 @Module 装饰器中给我们一个参数,我们可以定义模块的范围。我们不需要更多样板或装饰器等。
    • If you want to discuss more on Discord, I'm rather active there。我不明白为什么这个库需要来自主应用程序的配置,或者你期望找到什么样的力量,但你是对的,很难用这么少的字符来解释
    • 您的帖子非常详尽,谢谢。但如果我有任何疑问,我一定会与那里的人联系。 :)
    猜你喜欢
    • 2015-08-06
    • 2019-05-12
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 1970-01-01
    • 2022-10-21
    • 1970-01-01
    • 2022-12-20
    相关资源
    最近更新 更多