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. πŸ“šβœ¨

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Image of Docusign

πŸ› οΈ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more