From 359904d0d0d70fc1a1ce67fa7dd42458a3ed5f1f Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Tue, 27 Oct 2015 12:57:50 -0700 Subject: [PATCH] (docs) devguide dependency injection: correct provider terminology in chapter and glossary --- .../ts/latest/guide/dependency-injection.jade | 72 +++++++++++-------- public/docs/ts/latest/guide/glossary.jade | 72 +++++++++++-------- 2 files changed, 83 insertions(+), 61 deletions(-) diff --git a/public/docs/ts/latest/guide/dependency-injection.jade b/public/docs/ts/latest/guide/dependency-injection.jade index c8fab3f81f..4493e9ed43 100644 --- a/public/docs/ts/latest/guide/dependency-injection.jade +++ b/public/docs/ts/latest/guide/dependency-injection.jade @@ -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? + + + 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) diff --git a/public/docs/ts/latest/guide/glossary.jade b/public/docs/ts/latest/guide/glossary.jade index 2adc35c2e7..2c5dda7828 100644 --- a/public/docs/ts/latest/guide/glossary.jade +++ b/public/docs/ts/latest/guide/glossary.jade @@ -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