问题
In the Angular2 component configuration providers
is one of the keys that we could specify. How are these providers defined and what are they used for?
@Component({
..
providers: [..],
..
})
Note:
Angular2 documentation is gradually maturing but still sparse. It currently defines providers as:
An array of dependency injection providers for services that the component requires.
This recursive definition isn't very helpful. A more detailed explanation with an example would really help.
回答1:
Providers are usually singleton (one instance) objects, that other objects have access to through dependency injection (DI).
If you plan to use an object multiple times, for example Http
service in different components, you can ask for same instance of that service (reuse it). You do that with the help of DI by providing a reference to the same object that DI creates for you.
@Component){
..
providers: [Http]
}
..instead of creating new object every time:
@Component){}
class Cmp {
constructor() {
// this is pseudo code, doens't work
this.http = new Http(...options);
}
}
This is an approximation, but that's the general idea behind Dependency Injection - let the framework handle creation and maintenance of reusable objects... Provider is Angular's term for these reusable objects (dependencies).
回答2:
Register injectables
Providers make injectables known to Angular's DI and define the scope of an injectable (service).
Hierarchy of injectors
Angular's DI creates a tree of injectors (parent > child > grandchild >...) that resembles the structure of your components and directives.
Single instance per provider
Providers are maintained per injector. Each provider provides a single instance of an injectable.
Provider lookup
When a component or directive has a dependency (constructor parameter), DI starts looking on this component's injector for providers. If it has one it requests the instance from this provider and injects it.
If the injector doesn't have a provider for the requested key (type) then the parent injector is visited, up to the root (bootstrap) until a provider is found and its instance can be injected. (If no provider is found DI throws an error).
Define the scope of an injectable instance
This way you can define the scope of a shared service, because DI starts looking from the component where an instance is requested upwards until it finds one.
Singleton or not
How many places you provide an injectable determines how many instances will be created (they are only instantiated if actually requested).
If you want a single instance for your whole application, then provide an injectable only once at the root component (or with bootstrap(AppComponent, [...])
which results in the same behavior.
If you want a new instance for each component A
, then add it to providers of the component A
.
(update) NgModule lazy and non-lazy
With the introduction of NgModule
modules, additional levels were introduced. Providers registered with non-lazy-loaded modules are above the root component in the hierarchy.
Lazy-loaded modules are above the components and directives loaded by these components.
Because providers are read-only after an injector is created, there is no way to add providers from lazy loaded modules to the root injector. Therefore, lazy loaded modules get their own root scope.
See also https://stackoverflow.com/a/45231440/217408
回答3:
Think of providers like a recipe that tells angular how to inject a service.
We often declare providers in angular this way:
providers: [AnyService]
This is just a short hand for this:
[new Provider(AnyService, {useClass: AnyService})]
Both approaches are saying: Whenever someone requires "AnyService", provide the class "AnyService"
See that even though I'm providing the same class in the example above, in another scenario I could do something like this.
[new Provider(AnyService, {useClass: AnyServiceCustom})]
But in both scenarios, constructor would remain the same:
constructor( private _anyService: AnyService) {
}
To understand it better you need to understand how dependency injection works in Angular 2 as providers are directly related to it.
This is a must-read for every angular 2 developer.
https://angular.io/docs/ts/latest/guide/dependency-injection.html?The%20Provider%20class%20and%20provide%20function#!#injector-providers
回答4:
Add @Sasxa words, I want to point to Pro Angular book by Adam Freeman (chapter 20 (Using Service Providers)) for better, clear and detailed explanation with amazing examples.
Providers are classes that create and manage service objects the first time that Angular needs to resolve a dependency.Providers is used to register the classes to an angular module as a service.And then, this service classes can be used by other components during the itself creation phase in the module.
"Services are objects that provide common functionality to support other building blocks in an application, such as directives, components, and pipes. What’s important about services is the way that they are used, which is through a process called dependency injection. Using services can increase the flexibility and scalability of an Angular application, but dependency injection can be a difficult topic to understand." (Pro Angular (chapter 20))
Actually services can manage to distrubute objects as services using by dependency injection.
import { Injectable } from "@angular/core";
export enum LogLevel {DEBUG, INFO, ERROR}
@Injectable()
export class LogService {
minimumLevel: LogLevel = LogLevel.INFO;
logInfoMessage(message: string){
this.logMessage(LogLevel.INFO, message);
}
}
@Component({
selector: "example",
templateUrl: "example.component.html"
})
export class exampleComponent {
constructor(logService: LogService) {};
//to do impl
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [ BrowserModule ],
providers: [ LogService ],
declarations: [ ExampleComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
回答5:
import { service_name} from '../path';
@Component({
selector: 'selector_name',
templateUrl: './html file name ',
styleUrls: ['./css file name '],
providers: [ ./'service_name'];
})
export class AppComponent {
constructor(private Service_name: service_name) {
//enter code here
}
来源:https://stackoverflow.com/questions/37867503/what-are-providers-in-angular2