使用 registerAsync 导入模块时,Nest 无法解析依赖项

时间:2021-01-30 13:44:38

标签: typescript nestjs

我正在尝试使用 registerAsync 导入模块并使用我的模块中的提供程序对其进行配置,但它引发了一个错误,无法找到该提供程序。我错过了什么?

我的代码:

import { CacheModule, Module } from '@nestjs/common';

@Module({
  imports:     [
    CacheModule.registerAsync({
      useFactory: async (options) => ({
        ttl: options.ttl,
      }),
      inject: ['MY_OPTIONS'],
    }),
  ],
  providers:   [
    {
      provide:  'MY_OPTIONS',
      useValue: {
        ttl: 60,
      },
    },
  ],
})
export class AppModule {
}

错误:

<块引用>

错误:Nest 无法解析 CACHE_MODULE_OPTIONS (?) 的依赖关系。请确保索引 [0] 处的参数 MY_OPTIONS 在 CacheModule 上下文中可用。

上面的例子是我的代码的简化。但主要问题保持不变:我在 AppModule 中有一个提供程序,我在 CacheModule.registerAsync() 函数中需要它。

如果有人想尝试解决这个问题,我创建了一个非常简单的存储库:https://github.com/MickL/nestjs-inject-existing-provider

2 个答案:

答案 0 :(得分:2)

我认为问题在于“CacheModule.registerAsync”和“AppModule”在不同级别工作,因此在“AppModule”上定义提供程序并不能使其可用于“CacheModule.registerAsync”。

假设我们将“MY_OPTIONS”移动到另一个模块:“CacheConfigModule”,它可能看起来像:

CacheConfigModule.ts

import { Module } from '@nestjs/common';

@Module({
  providers: [
    {
      provide: 'MY_OPTIONS',
      useValue: {
        ttl: 60
      }
    }
  ],
  exports: ['MY_OPTIONS']
})
export class CacheConfigModule {}

AppModule.ts

import { CacheModule, Module } from '@nestjs/common';
import { CacheConfigModule } from './CacheConfigModule';

@Module({
  imports: [
    CacheConfigModule,
    CacheModule.registerAsync({
      imports: [CacheConfigModule],
      useFactory: async (options) => ({
        ttl: options.ttl
      }),
      inject: ['MY_OPTIONS']
    })
  ]
})
export class AppModule {}

答案 1 :(得分:0)

这有点奇怪,但即使它是相同的 @Module,您也需要像这样明确地指示依赖项管理器进行导入和导出:

import { CacheModule, Module } from '@nestjs/common';

@Module({
  imports:     [
    CacheModule.registerAsync({
      imports: [AppModule], // <-- ADDED
      useFactory: async (options) => {
        console.log('MY_OPTIONS', options) // <-- LOGS FINE upon NestFactory.create(AppModule)
        return {
        ttl: options.ttl,
        }
        },
      inject: ['MY_OPTIONS'],
    }),
  ],
  providers:   [
    {
      provide:  'MY_OPTIONS',
      useValue: {
        ttl: 60,
      },
    },
  ],
  exports: ['MY_OPTIONS'] // <-- ADDED
})
export class AppModule {
}

已编辑

根据您的存储库和特别文件 src/my-lib.module.ts,以下内容似乎有效(仍然不确定它是否完全解决了根本问题):

export class MyLibModule {
  // changed to async version by returning Promise
  static register(options: ModuleOptions): Promise<DynamicModule> {
    // keeps the ref to newly created module
    const OptionsModule = MyLibOptionsModule.register(options)
    // prints 'true', but still importing MyLibOptionsModule does not work
    console.log('who-am-i', OptionsModule.module === MyLibOptionsModule)
    return Promise.resolve({
      module: MyLibModule,
      imports: [
        // OptionsModule, // seems not needed
        HttpModule.registerAsync({
          useFactory: ((options: ModuleOptions) => {
            console.log("Works:", options);
            return {
              url: options.externalApiUrl,
              timeout: options.timeout
            };
          }),
          // importing via newly created ref does work
          imports: [OptionsModule],
          inject: [MODULE_OPTIONS]
        })
      ]
    });
  }
}