Reputation: 794
I build NestJS
projecct with many modules and recently I got lost in them a bit, My last thing which I'm doing was added QueueService
to my ProjectService
and ProjectModule
, but after launch whole app, the compiler throw me this:
Error: Nest can't resolve dependencies of the QueueService (UtilsService, UserService, Connection, ?). Please make sure that the argument Object at index [3] is available in the ProjectModule context.
The argument at the index[3] at QueueService
is ProjectService
, so why they want from me to import ProjectModule/ProjectService
into my ProjectModule
? :P
here is my all code:
@Injectable()
export class ProjectService {
constructor(
private conn: Connection,
private utilsService: UtilsService,
private userService: UserService,
private notificationService: NotificationsService,
private queueService: QueueService
) { }
@Module({
imports: [
PassportModule.register({ defaultStrategy: 'jwt'})
],
providers: [ProjectService, UtilsService, UserService, NotificationsService, QueueService ],
controllers: [ProjectController],
exports: [ProjectService]
})
export class ProjectModule {}
@Injectable()
export class QueueService {
constructor(
readonly conn: Connection,
readonly utilsService: UtilsService,
readonly userService: UserService,
readonly projectService: ProjectService
){}
}
@Module({
imports: [
AuthModule,
PassportModule.register({ defaultStrategy: 'jwt'})],
providers: [QueueService , UtilsService, UserService, NotificationsService, ProjectService],
controllers: [QueueController ],
exports: [PassportModule]
})
export class QueueModule {}
AppModule
@Module({
imports: [
...,
TypeOrmModule.forRootAsync({
useClass: TypeOrmConfigService
}),
PassportModule.register({ defaultStrategy: 'jwt'}),
JwtModule.register({
secret: 'secretKey'
}),
ScheduleModule.forRoot(),
...,
...,
QueueModule,
...,
...,
ProjectModule,
...,
...,
...
],
controllers: [..., ..., ..., ..., ...],
providers: [ ..., ..., ..., ..., ...,ProjectService, ..., ..., QueueService],
})
export class AppModule {}
thanks for any help, I stuck here for 3-4h and I do not know what can I do more :(
////////////////////////////////////
Upvotes: 3
Views: 1422
Reputation: 70600
Okay, lots to unpack here. So you've got circular dependencies between your services and you should have circular dependencies between your modules. What's happening right now is that you're creating two instances of QueueService
and two instances of ProjectService
. However, because these services depend on each other, there isn't a way for Nest to properly instantiate them (at least how you have it currently).
So, the quick and easy fix here, if you want two of each, is to add the proper forwardRef
for the circularly dependent classes.
@Injectable()
export class QueueService {
constructor(
readonly conn: Connection,
readonly utilsService: UtilsService,
readonly userService: UserService,
@Inject(forwardRef(() => ProjectService))
readonly projectService: ProjectService
){}
}
@Injectable()
export class ProjectService {
constructor(
private conn: Connection,
private utilsService: UtilsService,
private userService: UserService,
private notificationService: NotificationsService,
@Inject(forwardref(() => QueueService))
private queueService: QueueService
) { }
Now if that's all you want, great, feel free to stop reading here and go about your business.
So what should be happening? If you want true singletons of each service (services only created once) you should be sharing the providers via the modules they belong to and importing the module, not creating a new provider
value. As your ProjectModule
and QueueModule
are circularly dependent, you'll need to once again use forwardRef
. The services above are still valid, so I won't worry about re-writing those, but your modules should look like below:
@Module({
imports: [
AuthModule,
forwardRef(() => ProjectModule),
PassportModule.register({ defaultStrategy: 'jwt'})],
providers: [QueueService , UtilsService, UserService, NotificationsService],
controllers: [QueueController ],
exports: [PassportModule, QueueService]
})
export class QueueModule {}
@Module({
imports: [
forwardref(() => QueueModule),
PassportModule.register({ defaultStrategy: 'jwt'})
],
providers: [ProjectService, UtilsService, UserService, NotificationsService ],
controllers: [ProjectController],
exports: [ProjectService]
})
export class ProjectModule {}
You should absolutely look into your UtilsModule
, NotificationsModule
, and UserModule
to clean up their exports, and re-use the module instead of new provider instances as well.
Upvotes: 8