(docs) devguide dependency injection: correct provider terminology in chapter and glossary

This commit is contained in:
Ward Bell 2015-10-27 12:57:50 -07:00 committed by Naomi Black
parent 963f67ea07
commit 359904d0d0
2 changed files with 83 additions and 61 deletions

View File

@ -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`.
Isn't that always the case? Not always.
The first parameter is the [token](#token) that serves as the key for both locating a dependency value
and registering the provider.
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
@ -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.
@ -508,24 +514,30 @@ 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?
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.
<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.
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)

View File

@ -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).
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.
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.
There are other ways to create tokens and recipes.
See [Dependency Injection](#dependency-injection) chapter to learn more.
.l-main-section
:markdown