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) {
}
}
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.
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.
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.
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.
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:
emitDecoratorMetadata
and experimentalDecorators
- need to be set to true
@Injectable()
decorator, otherwise the metadata for their dependencies won't be emitted)I've written an in-depth article about that topic here
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With