DEV Community

Cover image for Understanding Dependency Injection in NestJS with a Book Service Example
Abhinav
Abhinav

Posted on

2 1

Understanding Dependency Injection in NestJS with a Book Service Example

Dependency Injection (DI) in NestJS simplifies the process of managing dependencies between services and classes. Let’s explore it using a BookService example to demonstrate how DI works in NestJS. πŸš€


🎯 Scenario

We want to build an application that:

  1. Retrieves a list of books from a database. πŸ“–
  2. Formats the books for display. ✨

We’ll use the following services:

  1. BookService: Handles book-related logic. πŸ› οΈ
  2. DatabaseService: Handles database interactions. πŸ’Ύ

πŸ› οΈ Step 1: Creating the DatabaseService

The DatabaseService simulates retrieving data from a database.

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

@Injectable()
export class DatabaseService {
  private books = [
    { id: 1, title: 'The Great Gatsby', author: 'F. Scott Fitzgerald' },
    { id: 2, title: '1984', author: 'George Orwell' },
    { id: 3, title: 'To Kill a Mockingbird', author: 'Harper Lee' },
  ];

  getAllBooks() {
    return this.books;
  }
}
Enter fullscreen mode Exit fullscreen mode

πŸ› οΈ Step 2: Creating the BookService

The BookService depends on the DatabaseService to retrieve books and then formats the output.

import { Injectable } from '@nestjs/common';
import { DatabaseService } from './database.service';

@Injectable()
export class BookService {
  constructor(private readonly databaseService: DatabaseService) {}

  getFormattedBooks() {
    const books = this.databaseService.getAllBooks();
    return books.map((book) => `${book.title} by ${book.author}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

Here, the DatabaseService is injected into the BookService through the constructor. πŸ”—


πŸ“¦ Step 3: Registering Services in a Module

Both services need to be registered as providers in a module. πŸ—‚οΈ

import { Module } from '@nestjs/common';
import { BookService } from './book.service';
import { DatabaseService } from './database.service';

@Module({
  providers: [BookService, DatabaseService],
  exports: [BookService], // Exporting BookService for use in other modules
})
export class BookModule {}
Enter fullscreen mode Exit fullscreen mode

🌐 Step 4: Using the BookService in a Controller

We can now use the BookService in a controller to expose the functionality through an API.

import { Controller, Get } from '@nestjs/common';
import { BookService } from './book.service';

@Controller('books')
export class BookController {
  constructor(private readonly bookService: BookService) {}

  @Get()
  getBooks() {
    return this.bookService.getFormattedBooks();
  }
}
Enter fullscreen mode Exit fullscreen mode

πŸ“¦ Step 5: Adding the Controller to the Module

Update the BookModule to include the controller. πŸ“‘

import { Module } from '@nestjs/common';
import { BookService } from './book.service';
import { DatabaseService } from './database.service';
import { BookController } from './book.controller';

@Module({
  providers: [BookService, DatabaseService],
  controllers: [BookController],
})
export class BookModule {}
Enter fullscreen mode Exit fullscreen mode

πŸ› οΈ How Dependency Injection Works Here

  1. DatabaseService:

    • Declared as a provider using the @Injectable() decorator. πŸ› οΈ
    • Registered in the module. βœ…
    • Injected into the BookService. πŸ”—
  2. BookService:

    • Declared as a provider using the @Injectable() decorator. πŸ› οΈ
    • Injected into the BookController. πŸ”—
  3. IoC Container:

    • NestJS automatically resolves and injects the dependencies (DatabaseService β†’ BookService β†’ BookController). πŸ€–

✨ Example Output

When you make a GET request to /books, the response would look like:

[
  "The Great Gatsby by F. Scott Fitzgerald",
  "1984 by George Orwell",
  "To Kill a Mockingbird by Harper Lee"
]
Enter fullscreen mode Exit fullscreen mode

πŸŽ‰ Advantages of DI in NestJS

  1. Loose Coupling: BookService doesn’t need to know how DatabaseService works. πŸ”—
  2. Reusability: Services like DatabaseService can be reused across the app. ♻️
  3. Testing: Mock services can be injected during testing for isolated unit tests. πŸ§ͺ

πŸš€ Summary

Dependency Injection in NestJS automates the creation and wiring of dependencies. By using decorators like @Injectable(), @Module(), and constructor injection, we can build scalable and maintainable applications. πŸ› οΈ

With this approach, we’ve created a clean and reusable architecture for the BookService example, demonstrating the power and simplicity of DI in NestJS. πŸ“šβœ¨

Do your career a big favor. Join DEV. (The website you're on right now)

It takes one minute, it's free, and is worth it for your career.

Get started

Community matters

Top comments (0)

Cloudinary image

Video API: manage, encode, and optimize for any device, channel or network condition. Deliver branded video experiences in minutes and get deep engagement insights.

Learn more

πŸ‘‹ Kindness is contagious

Engage with a sea of insights in this enlightening article, highly esteemed within the encouraging DEV Community. Programmers of every skill level are invited to participate and enrich our shared knowledge.

A simple "thank you" can uplift someone's spirits. Express your appreciation in the comments section!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found this useful? A brief thank you to the author can mean a lot.

Okay