(docs) devguide dependency injection: correct provider terminology in chapter and glossary
This commit is contained in:
parent
963f67ea07
commit
359904d0d0
|
@ -375,27 +375,31 @@ include ../../../../_includes/_util-fns
|
||||||
|
|
||||||
What matters is that the injector knows what to do when something asks for a `HeroService`.
|
What matters is that the injector knows what to do when something asks for a `HeroService`.
|
||||||
|
|
||||||
### Provider mappings
|
### The Provider Class
|
||||||
When we registered the `HeroService` with the injector, we were actually registering
|
|
||||||
a mapping between the `HeroService` *token* and a provider that can create a `HeroService`.
|
|
||||||
|
|
||||||
When we wrote ...
|
When we wrote ...
|
||||||
```
|
```
|
||||||
import {bootstrap} from 'angular2/angular2';
|
[HeroService];
|
||||||
|
|
||||||
bootstrap(AppComponent, [HeroService]);
|
|
||||||
```
|
```
|
||||||
... Angular translated that statement into a mapping instruction involving the Angular `provide` method
|
we used a short-hand expression for provider registration.
|
||||||
|
Angular expanded that short-hand into a call to the Angular `provide` method
|
||||||
```
|
```
|
||||||
import {bootstrap, provide} from 'angular2/angular2';
|
[provide(HeroService, {useClass:HeroService})];
|
||||||
|
|
||||||
bootstrap(AppComponent, [
|
|
||||||
provide(HeroService, {useClass:HeroService})
|
|
||||||
]);
|
|
||||||
```
|
```
|
||||||
Of course we prefer the shorthand syntax - `[HeroService]` - when the provider and the token are the same class.
|
and the `provide` method in turn creates a new instance of the Angular
|
||||||
|
[Provider class](http://localhost:3000/docs/ts/latest/api/core/Provider-class.html):
|
||||||
|
```
|
||||||
|
[new Provider(HeroService, {useClass:HeroService})]
|
||||||
|
```
|
||||||
|
This provider instance associates a `HeroService` *token*
|
||||||
|
with code that can create an *instance* of a `HeroService`.
|
||||||
|
|
||||||
|
The first parameter is the [token](#token) that serves as the key for both locating a dependency value
|
||||||
|
and registering the provider.
|
||||||
|
|
||||||
Isn't that always the case? Not always.
|
The second parameter is a provider definition object
|
||||||
|
which we think of as a "recipe" for creating the dependency value.
|
||||||
|
There are many ways to create dependency values ... and many ways to write a recipe.
|
||||||
|
|
||||||
### Alternative Class Providers
|
### Alternative Class Providers
|
||||||
|
|
||||||
|
@ -424,7 +428,7 @@ include ../../../../_includes/_util-fns
|
||||||
return [ provide(HeroService, {useValue: emptyHeroService}) ];
|
return [ provide(HeroService, {useValue: emptyHeroService}) ];
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
Notice that we mapped with `useValue` instead of `useClass`.
|
Notice we defined the recipe with `useValue` instead of `useClass`.
|
||||||
|
|
||||||
### Factory Providers
|
### Factory Providers
|
||||||
|
|
||||||
|
@ -472,7 +476,7 @@ include ../../../../_includes/_util-fns
|
||||||
a fact we can't know until runtime.
|
a fact we can't know until runtime.
|
||||||
:markdown
|
:markdown
|
||||||
We use dependency injection everywhere so of course the factory function depends on
|
We use dependency injection everywhere so of course the factory function depends on
|
||||||
two injected services: `Logger` and `UserService`.
|
two injected services: `Logger` and `UserService`.
|
||||||
We declare those requirements in our provider definition object:
|
We declare those requirements in our provider definition object:
|
||||||
```
|
```
|
||||||
let heroServiceDefinition = {
|
let heroServiceDefinition = {
|
||||||
|
@ -484,15 +488,17 @@ include ../../../../_includes/_util-fns
|
||||||
:markdown
|
:markdown
|
||||||
The `useFactory` field tells Angular that the provider is a factory function and that its implementation is the `heroServiceFactory`.
|
The `useFactory` field tells Angular that the provider is a factory function and that its implementation is the `heroServiceFactory`.
|
||||||
|
|
||||||
The `deps` property is an array of provider mapping tokens.
|
The `deps` property is an array of [provider tokens](#token).
|
||||||
The `Logger` and `UserService` classes serve as tokens for their own class provider mappings.
|
The `Logger` and `UserService` classes serve as tokens for their own class providers.
|
||||||
:markdown
|
:markdown
|
||||||
Finally, we create the mapping and adjust the bootstrapping to include that mapping in its provider configuration.
|
Finally, we create the provider and adjust the bootstrapping to include that provider
|
||||||
|
among its provider registrations.
|
||||||
```
|
```
|
||||||
let heroServiceMapping = provide(HeroService, heroServiceDefinition);
|
let heroServiceProvider = provide(HeroService, heroServiceDefinition);
|
||||||
|
|
||||||
bootstrap(AppComponent, [heroServiceMapping, Logger, UserService]);
|
bootstrap(AppComponent, [heroServiceProvider, Logger, UserService]);
|
||||||
```
|
```
|
||||||
|
|
||||||
### String tokens
|
### String tokens
|
||||||
|
|
||||||
Sometimes we have an object dependency rather than a class dependency.
|
Sometimes we have an object dependency rather than a class dependency.
|
||||||
|
@ -507,25 +513,31 @@ include ../../../../_includes/_util-fns
|
||||||
```
|
```
|
||||||
We'd like to make this `config` object available for injection.
|
We'd like to make this `config` object available for injection.
|
||||||
We know we can register an object with a "Value Provider". But what do we use for the token?
|
We know we can register an object with a "Value Provider". But what do we use for the token?
|
||||||
|
|
||||||
|
<a id="token"></a>
|
||||||
|
Until now, we've always asked the class to play the token role
|
||||||
|
whether we wrote a provider with a class, value, or factory recipe.
|
||||||
|
This time we don't have a class to serve as a token. There is no `Config` class.
|
||||||
|
|
||||||
Until now, we've always had a class to use as the token for mapping.
|
Fortunately, the token can be a string, a class type, or an
|
||||||
The `HeroService` class was our token, whether we mapped it to another class, a value, or a factory provider.
|
[OpaqueToken](http://localhost:3000/docs/ts/latest/api/core/OpaqueToken-class.html).
|
||||||
This time we don't have a class. There is no `Config` class.
|
Internally, the `Provider` turns the string and class parameter into an `OpaqueToken`;
|
||||||
|
the injector locates dependency values and providers by this token.
|
||||||
Fortunately, a token can be either a JavaScript type (e.g. the class function) **or a string**. We'll map our configuration object
|
|
||||||
to a string!
|
We'll register our configuration object with a string-based token!
|
||||||
```
|
```
|
||||||
bootstrap(AppComponent, [
|
bootstrap(AppComponent, [
|
||||||
// other mappings //
|
// other providers //
|
||||||
provide('App.config', {useValue:config})
|
provide('App.config', {useValue:config})
|
||||||
]);
|
]);
|
||||||
```
|
```
|
||||||
Now let's update the `HeroesComponent` constructor so it can display the configured title.
|
|
||||||
|
Let's apply what we've learned and update the `HeroesComponent` constructor so it can display the configured title.
|
||||||
Right now the constructor signature is
|
Right now the constructor signature is
|
||||||
```
|
```
|
||||||
constructor(heroService: HeroService)
|
constructor(heroService: HeroService)
|
||||||
```
|
```
|
||||||
We might think we can write:
|
We might think we can add the `config` dependency by writing:
|
||||||
```
|
```
|
||||||
// FAIL!
|
// FAIL!
|
||||||
constructor(heroService: HeroService, config: config)
|
constructor(heroService: HeroService, config: config)
|
||||||
|
|
|
@ -143,35 +143,49 @@
|
||||||
Angular developers prefer to build applications by defining many simple parts
|
Angular developers prefer to build applications by defining many simple parts
|
||||||
that each do one thing well and then wire them together at runtime.
|
that each do one thing well and then wire them together at runtime.
|
||||||
|
|
||||||
These parts often rely on one another. An Angular [Component](#component)
|
These parts often rely on other parts. An Angular [Component](#component)
|
||||||
part might rely on a service part to get data or perform a calculation. When a
|
part might rely on a service part to get data or perform a calculation. When a
|
||||||
part "A" relies on another part "B", we say that "A" depends on "B" and
|
part "A" relies on another part "B", we say that "A" depends on "B" and
|
||||||
that "B" is a dependency of "A".
|
that "B" is a dependency of "A".
|
||||||
|
|
||||||
We developers have a choice. We can teach "A" to find or create "B" all by itself.
|
We can ask a "Dependency Injection System" to create "A"
|
||||||
Or we can ask a "Dependency Injection System"" to find or create "B" and deliver
|
for us and handle all the dependencies.
|
||||||
it to part "A" when "A" needs it.
|
If "A" needs "B" and "B" needs "C", the system resolves that chain of dependencies
|
||||||
|
and returns a fully prepared instance of "A".
|
||||||
|
|
||||||
These choices and their relative merits are the subject of
|
Angular provides and relies upon its own sophisticated
|
||||||
much discussion under the rubric. "Dependency Injection".
|
[Dependency Injection](./dependency-injection.html) system
|
||||||
We can read about that in many places including
|
|
||||||
[on the web here](https://en.wikipedia.org/wiki/Dependency_injection)
|
|
||||||
|
|
||||||
Angular strongly favors the Dependency Injection approach
|
|
||||||
and relies on its own sophisticated
|
|
||||||
[Dependency Injection System](./dependency-injection.html) system
|
|
||||||
to assemble and run applications by "injecting" application parts
|
to assemble and run applications by "injecting" application parts
|
||||||
where and when needed.
|
into other application parts where and when needed.
|
||||||
|
|
||||||
These parts (often called "dependencies") are created by [providers](#provider)
|
At the core is an [`Injector`](#injector) that returns dependency values on request.
|
||||||
that we register with an [injector](#injector) at the appropriate time.
|
The expression `injector.get(token)` returns the value associated with the given token.
|
||||||
|
|
||||||
Quite often the best time to register a provider is when
|
A token is an Angular type (`OpaqueToken`). We rarely deal with tokens directly; most
|
||||||
we [bootstrap](#bootstrap) the application
|
methods accept a class name (`Foo`) or a string ("foo") and Angular converts it
|
||||||
but there are other opportunities to register as well.
|
to a token. When we write `injector.get(Foo)`, the injector returns
|
||||||
|
the value associated with the token for the `Foo` class, typically an instance of `Foo` itself.
|
||||||
|
|
||||||
Learn more by reading the [Dependency Injection System](./dependency-injection.html) chapter.
|
Angular makes similar requests internally during many of its operations
|
||||||
|
as when it creates a [`Component`](#AppComponent) for display.
|
||||||
|
|
||||||
|
The `Injector` maintains an internal map of tokens to dependency values.
|
||||||
|
If the `Injector` can't find a value for a given token, it creates
|
||||||
|
a new value using a `Provider` for that token.
|
||||||
|
|
||||||
|
A [Provider](#provider) is a recipe for
|
||||||
|
creating new instances of a dependency value associated with a particular token.
|
||||||
|
|
||||||
|
An injector can only create a value for a given token if it has
|
||||||
|
a `Provider` for that token in its internal provider registry.
|
||||||
|
Registering providers is a critical preparatory step.
|
||||||
|
|
||||||
|
Angular registers some of its own providers with every injector.
|
||||||
|
We can register our own providers. Quite often the best time to register a `Provider`
|
||||||
|
is when we [bootstrap](#bootstrap) the application.
|
||||||
|
There are other opportunities to register as well.
|
||||||
|
|
||||||
|
Learn more in the [Dependency Injection](./dependency-injection.html) chapter.
|
||||||
:markdown
|
:markdown
|
||||||
## Directive
|
## Directive
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
|
@ -318,18 +332,14 @@
|
||||||
## Provider
|
## Provider
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:markdown
|
:markdown
|
||||||
Angular relies on [dependency injection](#dependency-injection) to create and deliver
|
A Provider creates a new instance of a dependency for the Dependency Injection system.
|
||||||
pieces of functionality to the application parts that need them. Those pieces are
|
It relates a lookup token to code - sometimes called a "recipe" - that can create a dependency value.
|
||||||
often called "dependencies".
|
|
||||||
|
|
||||||
Angular can't find or create these dependencies by itself. Something has to "provide" them.
|
For example, `new Provider(Foo, {useClass: Foo})` creates a `Provider`
|
||||||
That something is called a "Provider". A provider can be almost anything that can produce
|
that relates the `Foo` token to a function that creates a new instance of the `Foo` class.
|
||||||
the dependency although it is most often a class that we register with the
|
|
||||||
[dependency injector](injector).
|
There are other ways to create tokens and recipes.
|
||||||
|
See [Dependency Injection](#dependency-injection) chapter to learn more.
|
||||||
We typically register our application providers when we [bootstrap](#bootstrap) the application
|
|
||||||
but there are other opportunities to do that as well.
|
|
||||||
See the [Dependency Injection[(./dependency-injection.html)] chapter for details.
|
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:markdown
|
:markdown
|
||||||
|
|
Loading…
Reference in New Issue