Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How nestjs works and runs constructors with parameter

I'm new at nestJS and also can't find too much information about it so I also afraid to dive into source code it (also a beginner in typescript). I really wanna know how those stuffs work which I'll mention below

First: I'm watching the tutorial where we have service called Task

export class TasksController {
  constructor(private readonly tasksService: TasksService) { }

  Get()
  index() {
     this.tasksService.all();
  }
}

Here TasksService used as just a type, not as a class I guess. In normal typescript, I would write something like that

let task = new TasksController(new TasksService())

Then I would be able to call this.tasksService.all();

Second: How @Injectable(), @Inject(), @InjectRepository() etc works. Original docs are bit confusing :(

like image 271
Farhad Avatar asked Jan 22 '20 19:01

Farhad


1 Answers

Nest it built on the ideas of Angular which deals a lot with Dependency Injection and Separation of Concerns. These ideas come from more Object Oriented languages like Java and C++ and especially from frameworks like Spring/SpringBoot.

Introduction

With that out of the way, Nest does a lot of stuff by "wiring up" providers together to allow for developers to not worry about instantiating each class, and rather let the framework handle that for them. I'll talk about your second point first and hopefully it will help shed some light on the first point.

The Injectable Inject and InjectRepository Decorators

All decorators in typescript are used to set metadata. Nest will then read this metadata and respond to it accordingly. For the most part, this all is taken care of under the hood with how the DI system is set up.

  • @Injectable() tells Nest "Hey, this class is a provider* and as such it should be able to have values injected into it and be able to be injected into other providers. All of your services will be marked as @Injectable() along with a few special classes.

  • @Inject() is a decorator that takes in an injection token**. This tells Nest "Hey I want to inject the provider tied to the token I just gave you. Make an instance and inject it here. The token can be a string or a symbol, but it needs to be unique (i.e. not clash with another provider). Use can use the same token multiple times.

  • @InjectRepository()/@InjectModel() these are special @Inject() decorators that use the standard @Inject() decorator under the hood to keep the injection token in line with the injection tokens Nest already creates in the TypeormModule and the MongooseModule

How it works (kind of)

So now that we know a bit more about the metadata that the decorators are setting, let's talk about how Nest resolves dependencies. What nest does is it scans each class and finds metadata on if it is @Injectable() or not. (@Controller() and other decorators do set this). Then it looks at the classes in the the constructor and finds out if that class has an injection token (classes are just determined by name unless otherwise mentioned***). If not it checks if there is an @Inject() decorator for it and finds its specific value to use. If it finds a class it will instantiate it, save it in a cache, and provide it to the class. If it is a value, it is directly provided to the class.

To get more in depth, rally read up on DI and how other frameworks handle it as well. Angular is a great resource because that, as I said, is where Nest got a lot of inspiration from

Footnotes:

*exceptions include Guards, Interceptors, Pipes, and Filters. While these are @Injectable() they are not normal providers.

** this is true unless you are dealing with class member injection in which case you don't provide a token.

*** you can manage this with custom providers

like image 150
Jay McDoniel Avatar answered Nov 15 '22 06:11

Jay McDoniel