(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`.
|
||||
|
||||
### Provider mappings
|
||||
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`.
|
||||
### The Provider Class
|
||||
|
||||
When we wrote ...
|
||||
```
|
||||
import {bootstrap} from 'angular2/angular2';
|
||||
|
||||
bootstrap(AppComponent, [HeroService]);
|
||||
[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';
|
||||
|
||||
bootstrap(AppComponent, [
|
||||
provide(HeroService, {useClass:HeroService})
|
||||
]);
|
||||
[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
|
||||
|
||||
|
@ -424,7 +428,7 @@ include ../../../../_includes/_util-fns
|
|||
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
|
||||
|
||||
|
@ -472,7 +476,7 @@ include ../../../../_includes/_util-fns
|
|||
a fact we can't know until runtime.
|
||||
:markdown
|
||||
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:
|
||||
```
|
||||
let heroServiceDefinition = {
|
||||
|
@ -484,15 +488,17 @@ include ../../../../_includes/_util-fns
|
|||
:markdown
|
||||
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 `Logger` and `UserService` classes serve as tokens for their own class provider mappings.
|
||||
The `deps` property is an array of [provider tokens](#token).
|
||||
The `Logger` and `UserService` classes serve as tokens for their own class providers.
|
||||
: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
|
||||
|
||||
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 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.
|
||||
The `HeroService` class was our token, whether we mapped it to another class, a value, or a factory provider.
|
||||
This time we don't have a class. There is no `Config` class.
|
||||
|
||||
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!
|
||||
Fortunately, the token can be a string, a class type, or an
|
||||
[OpaqueToken](http://localhost:3000/docs/ts/latest/api/core/OpaqueToken-class.html).
|
||||
Internally, the `Provider` turns the string and class parameter into an `OpaqueToken`;
|
||||
the injector locates dependency values and providers by this token.
|
||||
|
||||
We'll register our configuration object with a string-based token!
|
||||
```
|
||||
bootstrap(AppComponent, [
|
||||
// other mappings //
|
||||
// other providers //
|
||||
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
|
||||
```
|
||||
constructor(heroService: HeroService)
|
||||
```
|
||||
We might think we can write:
|
||||
We might think we can add the `config` dependency by writing:
|
||||
```
|
||||
// FAIL!
|
||||
constructor(heroService: HeroService, config: config)
|
||||
|
|
|
@ -143,35 +143,49 @@
|
|||
Angular developers prefer to build applications by defining many simple parts
|
||||
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 "A" relies on another part "B", we say that "A" depends on "B" and
|
||||
that "B" is a dependency of "A".
|
||||
|
||||
We developers have a choice. We can teach "A" to find or create "B" all by itself.
|
||||
Or we can ask a "Dependency Injection System"" to find or create "B" and deliver
|
||||
it to part "A" when "A" needs it.
|
||||
We can ask a "Dependency Injection System" to create "A"
|
||||
for us and handle all the dependencies.
|
||||
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
|
||||
much discussion under the rubric. "Dependency Injection".
|
||||
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
|
||||
Angular provides and relies upon its own sophisticated
|
||||
[Dependency Injection](./dependency-injection.html) system
|
||||
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)
|
||||
that we register with an [injector](#injector) at the appropriate time.
|
||||
At the core is an [`Injector`](#injector) that returns dependency values on request.
|
||||
The expression `injector.get(token)` returns the value associated with the given token.
|
||||
|
||||
Quite often the best time to register a provider is when
|
||||
we [bootstrap](#bootstrap) the application
|
||||
but there are other opportunities to register as well.
|
||||
A token is an Angular type (`OpaqueToken`). We rarely deal with tokens directly; most
|
||||
methods accept a class name (`Foo`) or a string ("foo") and Angular converts it
|
||||
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
|
||||
## Directive
|
||||
.l-sub-section
|
||||
|
@ -318,18 +332,14 @@
|
|||
## Provider
|
||||
.l-sub-section
|
||||
:markdown
|
||||
Angular relies on [dependency injection](#dependency-injection) to create and deliver
|
||||
pieces of functionality to the application parts that need them. Those pieces are
|
||||
often called "dependencies".
|
||||
A Provider creates a new instance of a dependency for the Dependency Injection system.
|
||||
It relates a lookup token to code - sometimes called a "recipe" - that can create a dependency value.
|
||||
|
||||
Angular can't find or create these dependencies by itself. Something has to "provide" them.
|
||||
That something is called a "Provider". A provider can be almost anything that can produce
|
||||
the dependency although it is most often a class that we register with the
|
||||
[dependency injector](injector).
|
||||
|
||||
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.
|
||||
For example, `new Provider(Foo, {useClass: Foo})` creates a `Provider`
|
||||
that relates the `Foo` token to a function that creates a new instance of the `Foo` class.
|
||||
|
||||
There are other ways to create tokens and recipes.
|
||||
See [Dependency Injection](#dependency-injection) chapter to learn more.
|
||||
|
||||
.l-main-section
|
||||
:markdown
|
||||
|
|
Loading…
Reference in New Issue