
NestJS Providers With Examples – DZone Web Dev
In this post, we will be looking at NestJS Providers and how to use them in our application.
In the previous post, we looked into NestJS Controllers. It is important to know about controllers before learning about Providers in NestJS and therefore, I will recommend you go through that post before starting this one.
1. Concept behind NestJS Providers
The main concept behind Providers and NestJS, in general, is Dependency Injection.
But what is Dependency Injection?
In a nutshell, Dependency Injection is a design pattern in which a class requests for its dependencies from an external source rather than creating them. This external source can be the framework itself.
Since NestJS uses Typescript as a base, it becomes extremely easy to manage dependencies.
If you come from a background of other frameworks such as Spring Boot that utilize Dependency Injection, it will be immediately obvious to you. However, even if you are completely new to this topic, we will see detailed examples that will make things clear.
The main idea behind a Provider is that it can be injected as a dependency. In other words, objects can form relationships between each other. The function of connecting the dots is left to the NestJS runtime system.
I think this is enough description about Dependency Injections and Providers. Let’s see things in action.
2. Creating a Service
In our previous post, we understood how to create a controller class to handle incoming requests and provide a response. A typical application would usually not be so simple.
Usually, it is good practice to encapsulate the business logic in a separate class. Such a class is known as a service. The job of this class is to process the requests received by the controller and perform the business logic.
books.service.tsimport { Injectable } from "@nestjs/common";
import { Book } from '../interfaces/book.interface'
@Injectable()
export class BooksService {
private readonly books: Book[] = [];
create(book: Book) {
console.log(book)
this.books.push(book);
}
findAll(): Book[] {
return this.books;
}
}
If you see above, we have a class named BooksService.
What does this class do?
Well, it has two methods – one to create a new book and another to return all the books. Nothing fancy as such!
The important term to note here is the @Injectable() decorator above the signature of the class.
Now, you might wonder what is the role of this @Injectable() decorator.
To put it simply, this decorator attaches metadata to the class that make it possible for the BooksService to be managed by the Nest IOC container. In other words, it basically makes it possible for NestJS to inject this class wherever needed.
Another thing to note here is the Book interface. We define it in its own file as below:
book.interface.tsexport interface Book {
name: String,
author: String
}
3. Injecting the Dependency
Now that our service class is ready, we need to inject it into our Controller.
For this example, we create a new NestJS Controller as below:
book.controller.tsimport { Controller, Get, Body, HttpCode, Post} from "@nestjs/common";
import { Book } from "./interfaces/book.interface";
import { BooksService } from "./services/books.service";
@Controller('books')
export class BookController {
constructor(private booksService: BooksService) {}
@Get()
@HttpCode(200)
async findAll(): Promise<Book[]> {
return this.booksService.findAll()
}
@Post()
@HttpCode(201)
async create(@Body() book: Book){
this.booksService.create(book);
}
}
Let’s break down things step-by-step.
- This is a typical controller that has two handlers – one for incoming GET requests to fetch all books and the second for POST requests to create a new book.
- In the constructor for this class, we inject an instance of BooksService. Basically, we are telling that to function properly the BookController needs an instance of BooksService.
- Finally, we use the methods available in the BooksService to fetch all books and create a new book.
4. Registering the NestJS Provider
Now that we have defined the provider i.e. BooksService. We also have a consumer for this service i.e. the BookController. However, we still need to register the service with Nest so that it can perform the injection.
This registration is done in the app.module.ts as below by adding the service in the providers
array of the @Module() decorator.
app.module.tsimport { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { ABCController } from './abc.controller';
import { AppService } from './app.service';
import { BookController } from './book.controller';
import { BooksService } from './services/books.service';
@Module({
imports: [],
controllers: [AppController, ABCController, BookController],
providers: [AppService, BooksService],
})
export class AppModule {}
Once the above configuration is in place, NestJS will automatically be able to resolve the dependencies and create appropriate instances during application start-up time.
Conclusion
With this, we have successfully looked at NestJS Providers and their usage in wiring up dependencies by leveraging the concepts of Dependency Injection and Inversion of Control.
In the next post, we will be looking into NestJS Modules that can help us design our applications in a better way.
If you have any comments or queries, please mention them in the comments section below.
Credit: Source link