在 nestjs 模块中使用相互依赖的多个文件(工厂和实现)

Using multiple files(factory and implementation) which depend on each other in nestjs module

我正在尝试在我的 nestjs 模块中实现一个服务工厂,但遇到了依赖问题。

一切都在一个模块 (TaskModule) 中,我在里面有三个不同的 classes,应该可以在模块中使用(TaskService、TaskFactory、SendQueuedEmailsTask)。我猜问题是其中一个文件(TaskFactory)依赖于模块中的其他可注入文件(SendQueuedEmailsTask)?我得到的错误是:

 Nest can't resolve dependencies of the TaskFactory (?). Please make sure that the argument SendQueuedEmailsTask at index [0] is available in the TaskFactory context.
 
 Potential solutions:
 - If SendQueuedEmailsTask is a provider, is it part of the current TaskFactory?
 - If SendQueuedEmailsTask is exported from a separate @Module, is that module  imported within TaskFactory?
  @Module({
    imports: [ /* the Module containing SendQueuedEmailsTask */ ]
   })

代码如下:

TaskFactory 文件

@Injectable()
export class TaskFactory {
    constructor(private readonly sendQueuedEmailsTask: SendQueuedEmailsTask) {}

    createTask(type: TaskType) {
      if(type === 'sendQueuedEmailsTask') return this.sendQueuedEmailsTask;
    }
}

SendQueuedEmailsTask 实施:

@Injectable()
export class SendQueuedEmailsTask {
    readonly actionName = 'sendQueueEmail';

    process() {
      // task implementation details
    }
}

最后是如何在服务中使用,TaskService:

@Injectable()
export class TaskService {
    constructor(
        private readonly taskFactory: TaskFactory,
    ) {}
    
    execute(name: string){
      // using TaskFactory             
      const Task = this.taskFactory.createTask(name);
      Task.process();
    }
}

我认为问题出在我的 TaskModule 文件中:

@Module({
    imports: [
        SendQueuedEmailsTask,
        TaskFactory,
    ],
    providers: [TaskService],
    controllers: [TaskController],
    exports: [TaskService],
})
export class TaskModule {}

已经尝试将 SendQueuedEmailsTask 和 TaskFactory 放入模块的提供程序数组中,但消息保持不变。不知道我做错了什么,也许这不是在使用 DI 时实现工厂 class 的方法? 非常感谢任何帮助!

如您所述,SendQueuedEmailsTaskTaskFactory 应移至 providers 并从 imports 中删除。

imports 仅用于导入从其他模块导出的服务 (related doc),因此 SendQueuedEmailsTaskTaskFactory 不属于那里。

为了确保 Nestjs 找到您要注入的服务,您可以在 TokenModule:

中创建自己的注入令牌
// injection-tokens.ts
export enum InjectionTokens {
  SEND_QUEUED_EMAILS_TASK = 'TASK_MODULE/SEND_QUEUED_EMAILS_TASK',
  TASK_FACTORY = 'TASK_MODULE/TASK_FACTORY',
  TASK_SERVICE = 'TASK_MODULE/TASK_SERVICE',
}

然后创建提供者:

// Create providers.
@Module({
  providers: [
    { provide: InjectionTokens.SEND_QUEUED_EMAILS_TASK, useClass: SendQueuedEmailsTask },
    { provide: InjectionTokens.TASK_FACTORY, useClass: TaskFactory },
    { provide: InjectionTokens.TASK_SERVICE, useClass: TaskService },
  ],
  controllers: [TaskController],
  exports: [
    { provide: InjectionTokens.TASK_SERVICE, useClass: TaskService },
  ],
})
export class TaskModule {}

并在您的 类:

中注入服务
// Inject services.
@Injectable()
export class TaskFactory {
  constructor(@Inject(InjectionTokens.SEND_QUEUED_EMAILS_TASK) private readonly sendQueuedEmailsTask: SendQueuedEmailsTask) {}

  // ...
}

@Injectable()
export class TaskService {
  constructor(@Inject(InjectionTokens.TASK_FACTORY) private readonly taskFactory: TaskFactory) {}
    
  // ...
}

它更冗长,但优点是您可以更好地控制注入并避免跨不同模块的服务名称冲突。