angular-cn/aio/content/guide/providers.md

148 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Providers
# 服务提供商
#### Prerequisites:
#### 前提条件:
* A basic understanding of [Bootstrapping](guide/bootstrapping).
对[引导](guide/bootstrapping)有基本的了解。
* Familiarity with [Frequently Used Modules](guide/frequent-ngmodules).
熟悉[常用模块](guide/frequent-ngmodules).
For the final sample app using the provider that this page describes,
see the <live-example></live-example>.
要想查看本页提到的这个带有特性模块的范例应用,参见 <live-example></live-example>
<hr>
## Create a service
## 创建服务
You can provide services to your app by using the `providers` array in an NgModule.
Consider the default app generated by the CLI. In order to add a user service to it,
you can generate one by entering the following command in the terminal window:
你可以使用 NgModule 中的 `providers` 数组来为你的应用提供服务。
对于用 CLI 生成的默认应用,要想为它添加一个 `user` 服务,你可以在终端窗口中输入如下命令来生成一个:
```sh
ng generate service User
```
This creates a service called `UserService`. You now need to make the service available in your
app's injector. Update `app.module.ts` by importing it with your other import statements at the top
of the file and adding it to the `providers` array:
这将会创建一个名叫 `UserService` 的服务。你现在要让该服务在你的应用注入器中可用,就要修改 `app.module.ts` 文件。先在文件的顶部导入它,然后把它加入 `providers` 数组中:
<code-example path="providers/src/app/app.module.ts" title="src/app/app.module.ts" linenums="false">
</code-example>
## Provider scope
## 提供商的作用域
When you add a service provider to the `providers` array of the root module, its available throughout the app. Additionally, when you import a module that has providers, those providers are also available to all the classes in the app as long they have the lookup token. For example, if you import the `HttpClientModule` into your `AppModule`, its providers are then available to the entire app and you can make HTTP requests from anywhere in your app.
当你把服务提供商添加到根模块的 `providers` 数组中时,它就在整个应用程序中可用了。
另外,当你导入一个带有服务提供商的模块时,其中的服务提供商也同样对整个应用中的类是可用的 —— 只要它们有供查找用的服务令牌。
比如,如果你把 `HttpClientModule` 导入了 `AppModule`,它里面的提供商就是对整个应用可用的,你可以在应用的任何地方发起 HTTP 请求。
## Limiting provider scope by lazy loading modules
## 使用惰性加载模块限制提供商的作用域
In the basic CLI generated app, modules are eagerly loaded which means that they are all loaded when the app launches. Angular uses an injector system to make things available between modules. In an eagerly loaded app, the root application injector makes all of the providers in all of the modules available throughout the app.
在 CLI 生成的基本应用中模块是立即加载的这意味着它们都是由本应用启动的Angular 会使用一个依赖注入体系来让一切服务都在模块间有效。对于立即加载式应用,应用中的根注入器会让所有服务提供商都对整个应用有效。
This behavior necessarily changes when you use lazy loading. Lazy loading is when you load modules only when you need them; for example, when routing. They arent loaded right away like with eagerly loaded modules. This means that any services listed in their provider arrays arent available because the root injector doesnt know about these modules.
当使用惰性加载时,这种行为需要进行改变。惰性加载就是只有当需要时才加载模块,比如路由中。它们没办法像立即加载模块那样进行加载。这意味着,在它们的 `providers` 数组中列出的服务都是不可用的,因为根注入器并不知道这些模块。
<!-- KW--Make diagram here -->
<!-- KW--per Misko: not clear if the lazy modules are siblings or grand-children. They are both depending on router structure. -->
When the Angular router lazy-loads a module, it creates a new injector. This injector is a child of the root application injector. Imagine a tree of injectors; there is a single root injector and then a child injector for each lazy loaded module. The router adds all of the providers from the root injector to the child injector. When the router creates a component within the lazy-loaded context, Angular prefers service instances created from these providers to the service instances of the application root injector.
当 Angular 的路由器惰性加载一个模块时,它会创建一个新的注入器。这个注入器是应用的根注入器的一个子注入器。想象一棵注入器树,它有唯一的根注入器,而每一个惰性加载模块都有一个自己的子注入器。路由器会把根注入器中的所有提供商添加到子注入器中。如果路由器在惰性加载时创建组件, Angular 会更倾向于使用从这些提供商中创建的服务实例,而不是来自应用的根注入器的服务实例。
Any component created within a lazy loaded modules context, such as by router navigation, gets the local instance of the service, not the instance in the root application injector. Components in external modules continue to receive the instance created for the application root.
任何在惰性加载模块的上下文中创建的组件(比如路由导航),都会获取该服务的局部实例,而不是应用的根注入器中的实例。而外部模块中的组件,仍然会收到来自于应用的根注入器创建的实例。
Though you can provide services by lazy loading modules, not all services can be lazy loaded. For instance, some modules only work in the root module, such as the Router. The Router works with the global location object in the browser.
虽然你可以使用惰性加载模块来提供实例,但不是所有的服务都能惰性加载。比如,像路由之类的模块只能在根模块中使用。路由器需要使用浏览器中的全局对象 `location` 进行工作。
## Limiting provider scope with components
## 使用组件限定服务提供商的作用域
Another way to limit provider scope is by adding the service you want to limit to the components
`providers` array. Component providers and NgModule providers are independent of each other. This
method is helpful for when you want to eagerly load a module that needs a service all to itself.
Providing a service in the component limits the service only to that component (other components in
the same module cant access it.)
另一种限定提供商作用域的方式是把要限定的服务添加到组件的 `providers` 数组中。组件中的提供商和 NgModule 中的提供商是彼此独立的。
当你要立即加载一个自带了全部所需服务的模块时,这种方式是有帮助的。
在组件中提供服务,会限定该服务只能在该组件中有效(同一模块中的其它组件不能访问它)。
<code-example path="providers/src/app/app.component.ts" region="component-providers" title="src/app/app.component.ts" linenums="false">
</code-example>
## Providing services in modules vs. components
## 在模块中提供服务还是在组件中?
Generally, provide services the whole app needs in the root module and scope services by providing them in lazy loaded modules.
通常,要在根模块中提供整个应用都需要的服务,在惰性加载模块中提供限定范围的服务。
The router works at the root level so if you put providers in a component, even `AppComponent`, lazy loaded modules, which rely on the router, cant see them.
路由器工作在根级,所以如果你把服务提供商放进组件(即使是 `AppComponent`)中,那些依赖于路由器的惰性加载模块,将无法看到它们。
<!-- KW--Make a diagram here -->
Register a provider with a component when you must limit a service instance to a component and its component tree, that is, its child components. For example, a user editing component, `UserEditorComponent`, that needs a private copy of a caching `UserService` should register the `UserService` with the `UserEditorComponent`. Then each new instance of the `UserEditorComponent` gets its own cached service instance.
当你必须把一个服务实例的作用域限定到组件及其组件树中时,可以使用组件注册一个服务提供商。
比如,用户编辑组件 `UserEditorComponent`,它需要一个缓存 `UserService` 实例,那就应该把 `UserService` 注册进 `UserEditorComponent` 中。
然后,每个 `UserEditorComponent` 的实例都会获取它自己的缓存服务实例。
<hr>
## More on NgModules
## 关于 NgModule 的更多知识
You may also be interested in:
你可能还对下列内容感兴趣:
* [Singleton Services](guide/singleton-services), which elaborates on the concepts covered on this page.
[单例服务](guide/singleton-services)详细解释了本页包含的那些概念。
* [Lazy Loading Modules](guide/lazy-loading-ngmodules).
[惰性加载模块](guide/lazy-loading-ngmodules)。
* [NgModule FAQ](guide/ngmodule-faq).
[NgModule 常见问题](guide/ngmodule-faq)。