在 angular 2 (Beta) 中将一项服务注入另一项服务的最佳方法是什么? [英] What's the best way to inject one service into another in angular 2 (Beta)?
问题描述
我知道如何将服务注入到组件中(通过@Component),但是如何使用 DI 在组件之外传递服务?
I know how to inject a service into a component (via @Component), but how can I use DI to pass around services outside of components?
换句话说,我不想这样做:
In other words, I don't want to do this:
export class MyFirstSvc {
}
export class MySecondSvc {
constructor() {
this.helpfulService = new MyFirstSvc();
}
}
export class MyThirdSvc {
constructor() {
this.helpfulService = new MyFirstSvc();
}
}
推荐答案
是的,首先要在每个要注入的服务上添加 @Injectable
装饰器.事实上,Injectable
这个名字有点阴险.这并不意味着该类将是可注入的",但它会进行装饰,以便可以注入构造函数参数.有关更多详细信息,请参阅此 github 问题:https://github.com/angular/angular/issues/4404.
Yes, the first thing is to add the @Injectable
decorator on each services you want to inject. In fact, the Injectable
name is a bit insidious. It doesn't mean that the class will be "injectable" but it will decorate so the constructor parameters can be injected. See this github issue for more details: https://github.com/angular/angular/issues/4404.
这里是我对注入机制的理解.当为一个类设置 @Injectable
装饰器时,Angular 将尝试为当前执行链的注入器中的相应类型创建或获取实例.事实上,Angular2 应用程序不仅有一个注入器,而且还有一棵注入器树.它们与整个应用程序和组件隐式关联.此级别的一个关键特征是它们以分层方式链接在一起.这个注入器树映射了组件树.没有为服务"定义注入器.
Here is my understanding of the injection mechanism. When setting an @Injectable
decorator for a class, Angular will try to create or get instances for corresponding types in the injector for the current execution chain. In fact, there is not only one injector for an Angular2 application but a tree of injectors. They are implicitly associated to the whole application and components. One key feature at this level is that they are linked together in a hierarchical way. This tree of injectors maps the tree of components. No injectors are defined for "services".
让我们举个例子.我有以下应用程序:
Let's take a sample. I have the following application:
Component
AppComponent
:在bootstrap
函数中创建Angular2应用程序时提供的我的应用程序的主要组件
Component
AppComponent
: the main component of my application that is provided when creating the Angular2 application in thebootstrap
function
@Component({
selector: 'my-app',
template: `
<child></child>
`,
(...)
directives: [ ChildComponent ]
})
export class AppComponent {
}
Component ChildComponent
:将在 AppComponent
组件中使用的子组件
Component ChildComponent
: a sub component that will be used within the AppComponent
component
@Component({
selector: 'child',
template: `
{{data | json}}<br/>
<a href="#" (click)="getData()">Get data</a>
`,
(...)
})
export class ChildComponent {
constructor(service1:Service1) {
this.service1 = service1;
}
getData() {
this.data = this.service1.getData();
return false;
}
}
两个服务,Service1
和 Service2
:Service1
被 ChildComponent
和 使用>Service2
由 Service1
Two services, Service1
and Service2
: Service1
is used by the ChildComponent
and Service2
by Service1
@Injectable()
export class Service1 {
constructor(service2:Service2) {
this.service2 = service2;
}
getData() {
return this.service2.getData();
}
}
<小时>
@Injectable()
export class Service2 {
getData() {
return [
{ message: 'message1' },
{ message: 'message2' }
];
}
}
以下是所有这些元素及其关系的概述:
Here is an overview of all these elements and there relations:
Application
|
AppComponent
|
ChildComponent
getData() --- Service1 --- Service2
在这样的应用程序中,我们有三个注入器:
In such application, we have three injectors:
- 可以使用
bootstrap
函数的第二个参数配置的应用程序注入器 - 可以使用该组件的
providers
属性配置的AppComponent
注入器.它可以看到"应用程序注入器中定义的元素.这意味着如果在此提供程序中找不到提供程序,它将自动在此父注入器中查找.如果在后者中没有找到,则会抛出provider not found"错误. ChildComponent
注入器将遵循与AppComponent
相同的规则.要注入组件执行的注入链中涉及的元素,将首先在此注入器中查找提供者,然后在AppComponent
中查找,最后在应用程序中查找.
- The application injector that can be configured using the second parameter of the
bootstrap
function - The
AppComponent
injector that can be configured using theproviders
attribute of this component. It can "see" elements defined in the application injector. This means if a provider isn't found in this provider, it will be automatically look for into this parent injector. If not found in the latter, a "provider not found" error will be thrown. - The
ChildComponent
injector that will follow the same rules than theAppComponent
one. To inject elements involved in the injection chain executed forr the component, providers will be looked for first in this injector, then in theAppComponent
one and finally in the application one.
这意味着当尝试将 Service1
注入到 ChildComponent
构造函数中时,Angular2 将查看 ChildComponent
注入器,然后进入 ChildComponent
注入器code>AppComponent一,最后进入应用一.
This means that when trying to inject the Service1
into the ChildComponent
constructor, Angular2 will look into the ChildComponent
injector, then into the AppComponent
one and finally into the application one.
由于Service2
需要注入Service1
,所以做同样的解析处理:ChildComponent
注入器,AppComponent代码>一和应用一.
Since Service2
needs to be injected into Service1
, the same resolution processing will be done: ChildComponent
injector, AppComponent
one and application one.
这意味着 Service1
和 Service2
都可以根据您的需要使用组件的 providers
属性在每个级别指定,第二个应用程序注入器的 bootstrap
函数的参数.
This means that both Service1
and Service2
can be specified at each level according to your needs using the providers
attribute for components and the second parameter of the bootstrap
function for the application injector.
这允许共享一组元素的依赖项实例:
This allows to share instances of dependencies for a set of elements:
- 如果您在应用程序级别定义提供者,则相应的创建实例将被整个应用程序(所有组件、所有服务……)共享.
- 如果您在组件级别定义提供者,则该实例将由组件本身、其子组件以及依赖链中涉及的所有服务"共享.
因此它非常强大,您可以根据自己的需要自由组织.
So it's very powerful and you're free to organize as you want and for your needs.
这是相应的 plunkr,您可以使用它:https://plnkr.co/edit/PsySVcX6OKtD3A9TuAEw?p=预览.
Here is the corresponding plunkr so you can play with it: https://plnkr.co/edit/PsySVcX6OKtD3A9TuAEw?p=preview.
Angular2 文档中的此链接可以帮助您:https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html.
This link from the Angular2 documentation could help you: https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html.
希望对您有所帮助(抱歉回答太长),蒂埃里
Hope it helps you (and sorry the long answer), Thierry
这篇关于在 angular 2 (Beta) 中将一项服务注入另一项服务的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!