Updated on 16 Apr, 202611 mins read 51 views

What are Providers?

A provider is any class that can be injected as a dependency.

Most commonly:

  • Services
  • Repositories
  • Helpers
  • Factories

Example:

@Injectable()
export class UsersService {
  getUsers() {
    return ['John', 'Jane'];
  }
}

This UsersService is a provider.

What is Dependency Injection (DI)?

Dependency Injection means:

Instead of creating dependencies manually, NestJS provides them automatically.

It is a design pattern where dependencies are provided by an external system (NestJS container) instead of being created manually.

Without DI:

const service = new UsersService();

With DI:

constructor(private usersService: UsersService) {}

Why DI?

  • Cleaner code
  • Easier testing
  • Loose coupling
  • Better scalability

How Providers Work in NestJS

NestJS has a built-in IoC (Inversion of Control) container.

Flow:

  1. You mark a class with @Injectable()
  2. Register it in a module
  3. NestJS creates and manages its instance
  4. Inject it wherever needed

Creating a Service (Provider)

Generating service:

nest generate service users

users.service.ts:

import { Injectable } from '@nestjs/common';

@Injectable()
export class UsersService {
  private users = [];

  findAll() {
    return this.users;
  }

  create(user: any) {
    this.users.push(user);
    return user;
  }
}

Registering Providers in Modules

Providers must be registered in a module:

import { Module } from '@nestjs/common';
import { UsersService } from './users.service';

@Module({
  providers: [UsersService],
})
export class UsersModule {}

Injecting Providers into Controllers

import { Controller, Get } from '@nestjs/common';
import { UsersService } from './users.service';

@Controller('users')
export class UsersController {

  constructor(private usersService: UsersService) {}

  @Get()
  getUsers() {
    return this.usersService.findAll();
  }
}

Provider Scope

By default, providers are singleton.

Types of scopes:

1 Singleton (default)

  • One instance shared across app

2 Request Scope

  • New instance per request

3 Transient Scope

  • New instance every time injected

Example:

@Injectable({ scope: Scope.REQUEST })

Custom Providers

Sometimes you need more control.

Types:

  • useClass
  • useValues
  • useFactory
  • useExisting

Example:

{
  provide: 'API_KEY',
  useValue: '123456'
}

Inject:

{
  provide: 'CONFIG',
  useFactory: () => {
    return { env: 'development' };
  }
}

Exporting Providers

To use a provider in another module:

@Module({
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

Interview Questions

Where are providers registered?

Inside the providers array of a module.

@Module({
  providers: [UsersService],
})

What is constructor-based injection?

Dependencies are injected through the class constructor.

constructor(private usersService: UsersService) {}

What happens if a provider is not registered in a module?

NestJS throws a runtime error saying it cannot resolve dependencies.

Can a provider be shared across modules?

Yes, by exporting it from one module and importing that module into another.

What is circular dependency?

When two providers depend on each other.

How do you resolve circular dependencies?

Using forwardRef():

@Inject(forwardRef(() => AuthService))
Buy Me A Coffee

Leave a comment

Your email address will not be published. Required fields are marked *