NodeJS 如何在NestJ中动态注入提供者

cotxawn7  于 2023-03-07  发布在  Node.js
关注(0)|答案(2)|浏览(269)

我的团队正在尝试确定一种动态DI的方法,这样就可以有一个批量插入点,而不需要拼写+导入每个模块。

@Module({
  ...
  providers: [
    WorkerService,
    WorkerResolver,
    Worker2Service,
    Worker2Resolver........
  ]
})

想要实现

var allModules = ... // logic here to include all my resolvers, or all my services

@Module({
  ...
  providers: [
    ...allModules
  ]
})
v8wbuo2f

v8wbuo2f1#

您可以使用glob包动态查找模块,然后使用NestJs动态模块特性动态加载它们。
假设您的所有辅助文件都存储在名为workers的目录中,扩展名为.worker.ts

@Module({})
    export class WorkerModule {
      static forRootAsync(): DynamicModule {
        return {
          module: WorkerModule ,
          imports: [WorkerCoreModule.forRootAsync()],
        };
      }
    }
export class WorkerCoreModule {

  static async forRootAsync(): Promise<DynamicModule> {
    // Feel free to change path if your structure is different
    const workersPath = glob.sync('src/**/workers/*.worker.ts');
    const workersRelativePathWithoutExt = modelsPath
      // Replace src, because you are probably running the code
      // from dist folder
      .map((path) => path.replace('src/', './../'))
      .map((path) => path.replace('.ts', ''));
    const workerProviders: Provider<any>[] = [];
    const importedModules = await Promise.all(
      workersRelativePathWithoutExt.map((path) => import(path)),
    );
    importedModules.forEach((modules) => {
      // Might be different if you are using default export instead
      const worker = modules[Object.keys(modules)[0]];
      workerProviders.push({
        provide: worker.name, 
        useValue: worker,
      });
    });

    return {
      module: WorkerCoreModule,
      providers: [...workerProviders],
      // You can omit exports if providers are meant to be used
      // only in this module
      exports: [...workerProviders],
    };
  }
}

现在假设你有一个简单的worker类,路径为src/anyModule/workers/simple-worker.ts,你可以这样使用它:

class WrokersService {
  constructor(@Inject('SimpleWorker') simpleWroker: SimpleWorker) {}
  .
  .
  .
}

如果您希望忽略@Inject('SimpleWorker')并自动注入模块(如NestJs服务),则需要对WorkerCoreModule进行以下更改:

workerProviders.push({
  provide: worker,
});

然而,为了使它工作,您需要确保您的worker类是用@injectable()修饰的。

js4nwp54

js4nwp542#

另一个答案是正确的,但不要使用useValue,而是尝试使用useClass

export class WorkerCoreModule {

  static async forRootAsync(): Promise<DynamicModule> {
    // Feel free to change path if your structure is different
    const workersPath = glob.sync('src/**/workers/*.worker.ts');
    const workersRelativePathWithoutExt = modelsPath
      // Replace src, because you are probably running the code
      // from dist folder
      .map((path) => path.replace('src/', './../'))
      .map((path) => path.replace('.ts', ''));
    const workerProviders: Provider<any>[] = [];
    const importedModules = await Promise.all(
    workersRelativePathWithoutExt.map((path) => import(path)),
    );
    importedModules.forEach((modules) => {
      // Might be different if you are using default export instead
      const worker = modules[Object.keys(modules)[0]];
      workerProviders.push({
        provide: worker.name, 
        useClass: worker,
      });
    });

    return {
      module: WorkerCoreModule,
      providers: [...workerProviders],
      // You can omit exports if providers are meant to be used
      // only in this module
      exports: [...workerProviders],
     };
  }
}

相关问题