Providers: Dependency Injection in NestJS
Understanding providers (services, repositories, factories, etc.), injecting dependencies, and the scope of providers.
NestJS Providers: Services
Providers
In NestJS, a Provider is a fundamental concept. It's a class annotated with @Injectable()
and responsible for handling dependencies. Providers can inject dependencies into other classes using dependency injection (DI). This promotes loose coupling and testability within your application. Think of them as building blocks for your application logic. They make your components reusable and manageable.
Providers can be of various types, including:
- Services
- Repositories
- Factories
- Helpers
- Custom Providers (using
useValue
,useFactory
, etc.)
Services
Services are a specific type of provider. They are the heart of your application's business logic. They are the classes that contain the actual code that performs actions, manipulates data, and interacts with external resources (like databases or APIs). They are designed to be reusable and testable components.
Learn about Services as a fundamental provider type in NestJS, responsible for encapsulating business logic and data manipulation.
Key aspects of Services in NestJS:
- Business Logic: Services contain the core logic of your application, such as creating users, processing payments, or fetching data from external sources.
- Data Manipulation: They handle data transformations and persistence. For instance, a service might interact with a database repository to store and retrieve data.
- Dependency Injection: Services can inject other providers (including other services, repositories, etc.) to perform their tasks.
- Reusability: Services are designed to be reusable across different parts of your application. You can inject the same service into multiple controllers or other services.
- Testability: Due to dependency injection, services are easily testable. You can mock the dependencies and test the service's logic in isolation.
Example Service
Here's a basic example of a NestJS service:
import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {
private readonly users = [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Doe' },
];
findAll() {
return this.users;
}
findOne(id: number) {
return this.users.find(user => user.id === id);
}
}
Explanation:
@Injectable()
: Marks the class as a provider, making it available for dependency injection.UsersService
: The name of our service.private readonly users
: A mock data array to represent user data. In a real application, this would likely interact with a database.findAll()
: A method that returns all users.findOne(id: number)
: A method that returns a user by ID.
Injecting the Service
To use this service in a controller, you would inject it using dependency injection:
import { Controller, Get, Param } from '@nestjs/common';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get()
findAll() {
return this.usersService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(+id);
}
}
Explanation:
- The
UsersService
is injected into theUsersController
's constructor. - The controller methods (
findAll
andfindOne
) then use the injected service to retrieve user data.