Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Angular2 manage dependency injection?

I understand that to inject a dependancy into an Angular2 component, I simply annotate an argument in its constructor, like here with ThingService. What I would like to understand is how Angular knows what to inject at runtime, as so far as I am aware, this is just TypeScript annotation and has no meaning at run time. What is the low level, internal mechanism of this to manage which providers are placed where in a component's constructor. If you were to roll this system yourself, how would it work. Is this a typescript mechanism I am not understanding?

@Component({
  selector: 'app-thing',
  templateUrl: './thing.component.html',
  styleUrls: ['./thing.component.scss']
})
export class ThingComponent {

  constructor(
    private thingService: ThingService) {
  }
}
like image 312
Mild Fuzz Avatar asked Jan 17 '17 11:01

Mild Fuzz


People also ask

How does Angular achieve dependency injection?

Providing dependencylink The first step is to add the @Injectable decorator to show that the class can be injected. The next step is to make it available in the DI by providing it. A dependency can be provided in multiple places: At the Component level, using the providers field of the @Component decorator.

Which decorator is used for dependency injection in Angular?

The @Injectable() decorator defines a class as a service in Angular and allows Angular to inject it into a component as a dependency. Likewise, the @Injectable() decorator indicates that a component, class, pipe, or NgModule has a dependency on a service. The injector is the main mechanism.

Which provider is used for dynamic dependency injection?

The useFactory provider key lets you create a dependency object by calling a factory function, as in the following example. The injector provides the dependency value by invoking a factory function, that you provide as the value of the useFactory key.

Which method is used for dependency injection?

constructor injection: the dependencies are provided through a class constructor. setter injection: the client exposes a setter method that the injector uses to inject the dependency. interface injection: the dependency provides an injector method that will inject the dependency into any client passed to it.


2 Answers

What happens under the hood is that TypeScript preserves the metadata in the generated ES5 code. So the annotation in your constructor isn't actually gone, it's available at runtime and then Angular's DI can take it from there.

TypeScript always preserves that metadata if the following requirements are fulfilled:

  1. Both compiler option properties - emitDecoratorMetadata and experimentalDecorators - need to be set to true
  2. There has to be at least one decorator on the class (that's why some service classes use the @Injectable() decorator, otherwise the metadata for their dependencies won't be emitted)

I've written an in-depth article about that topic here

like image 161
Pascal Precht Avatar answered Oct 04 '22 19:10

Pascal Precht


If I understood correctly you are asking for a more theoretical(js behind the ts) answer.

According to what I've read; angular2 injection system creates an instance of that provider object/function and uses that instance in that component when you define it like that in the constructor. If you haven't provided it in the component that you are using then it will go to it's parent component, up to the module that it's been used. Each level has its own map of provider instances and the component will use the first instance that it finds when it traverses the injection tree upwards.

So the provider will be a singleton instance up to the point it is defined.

like image 30
eko Avatar answered Oct 04 '22 19:10

eko