Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inject nestjs service from another module

I've got a PlayersModule and an ItemsModule.

I want to use the ItemsService in the PlayersService.

When I add it by injection:

import { Injectable } from '@nestjs/common';
import { InjectModel } from 'nestjs-typegoose';
import { ModelType, Ref } from 'typegoose';
import { Player } from './player.model';
import { Item } from '../items/item.model';
import { ItemsService } from '../items/items.service';

@Injectable()
export class PlayersService {
    constructor(
        @InjectModel(Player) private readonly playerModel: ModelType<Player>,
        private readonly itemsService: ItemsService){}

I get this nest error :

[Nest] 11592 - 2018-8-13 11:42:17 [ExceptionHandler] Nest can't resolve dependencies of the PlayersService (+, ?). Please make sure that the argument at index [1] is available in the current context.

Both modules are imported in the app.module.ts. Both services are working alone in their module.

like image 399
Fairydhwen Avatar asked Aug 13 '18 09:08

Fairydhwen


People also ask

How do I run a service from another module?

Another way to invoke a service from another module is to create an export with an SCA binding and then save the export. Locate the export in the Business Integration view, and drag it to another module. An import with a matching SCA binding is created in the second module.

How does dependency injection work in NestJS?

Dependency injection is an inversion of control (IoC) technique wherein you delegate instantiation of dependencies to the IoC container (in our case, the NestJS runtime system), instead of doing it in your own code imperatively.

What is @inject in NestJS?

ts, the @Injectable() decorator declares the CatsService class as a class that can be managed by the Nest IoC container. https://docs.nestjs.com/fundamentals/custom-providers#di-fundamentals. It declares a class to be recognized by Nest for future Dependency Injection, which are performed through @Inject(TokenName) .


4 Answers

You have to export the ItemsService in the module that provides it:

@Module({
  controllers: [ItemsController],
  providers: [ItemsService],
  exports: [ItemsService]
  ^^^^^^^^^^^^^^^^^^^^^^^
})
export class ItemsModule {}

and then import the exporting module in the module that uses the service:

@Module({
  controllers: [PlayersController],
  providers: [PlayersService],
  imports: [ItemsModule]
  ^^^^^^^^^^^^^^^^^^^^^^
})
export class PlayersModule {}

⚠️ Don't add the same provider to multiple modules. Export the provider, import the module. ⚠️

like image 103
Kim Kern Avatar answered Oct 18 '22 00:10

Kim Kern


Let' say you want to use AuthService from AuthModule in my TaskModule's controller

for that, you need to export authService from AuthModule

@Module({
    imports: [
     ....
    ],
    providers: [AuthService],
    controllers: [AuthController],
    exports:[AuthService]
  })
export class AuthModule {}
  

then in TaskModule, you need to import AuthModule (note: import AuthModule not the AuthService in TaskModule)

@Module({
    imports:[
      AuthModule
    ],
    controllers: [TasksController],
    providers: [TasksService]
  })
export class TasksModule {}

Now you should be able to use DI in TaskController

@Controller('tasks')
export class TasksController {
   constructor(private authService: AuthService) {}
   ...
}
  
like image 24
santonil2003 Avatar answered Oct 18 '22 01:10

santonil2003


The question is answered by Kim Kern. But I just want to remind people who read through this comment. Whenever you get this error, you should follow these steps that may help you easily figure out where the stuck is:

  • Make sure the Module which provides providers was imported.
  • Make sure the provider which you are using is exported.

For example, you have category module which contains category service, post module has post service and it has category service as a dependency:

@Module({
    controllers: [CategoryController],
    providers: [CategoryService],
    exports: [CategoryService] // Remember to export
  })
export class CategoryModule {}

And

@Module({
    imports: [CategoryModule], // Make sure you imported the module you are using
    controllers: [PostController],
    providers: [PostService]
  })
export class PostModule {}

Don't forget to use this annotation. Nest uses this to detect singleton class. In spring boot - Java, this one used to be called Bean. Read more:

@Injectable()  
export class PostService {
  constructor(private readonly categoryService: CategoryService // This will be auto injected by Nestjs Injector) {}
}
like image 7
Justin Dang Avatar answered Oct 18 '22 01:10

Justin Dang


I solved my problem by removing @Inject() from the argument in my constructor that was passing the exported service.

like image 5
Ben Stickley Avatar answered Oct 18 '22 00:10

Ben Stickley