在 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 的方法?
非常感谢任何帮助!
如您所述,SendQueuedEmailsTask
和 TaskFactory
应移至 providers
并从 imports
中删除。
imports
仅用于导入从其他模块导出的服务 (related doc),因此 SendQueuedEmailsTask
和 TaskFactory
不属于那里。
为了确保 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) {}
// ...
}
它更冗长,但优点是您可以更好地控制注入并避免跨不同模块的服务名称冲突。
我正在尝试在我的 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 的方法? 非常感谢任何帮助!
如您所述,SendQueuedEmailsTask
和 TaskFactory
应移至 providers
并从 imports
中删除。
imports
仅用于导入从其他模块导出的服务 (related doc),因此 SendQueuedEmailsTask
和 TaskFactory
不属于那里。
为了确保 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) {}
// ...
}
它更冗长,但优点是您可以更好地控制注入并避免跨不同模块的服务名称冲突。