什么是注入一个服务到另一个角2(测试版)的最好方法? [英] What's the best way to inject one service into another in angular 2 (Beta)?
问题描述
我知道如何注入到服务(通过@Component)一个组成部分,但我该如何使用DI来服务绕过组件之外吗?
在换句话说,我不想这样做:
出口类MyFirstSvc {}出口类MySecondSvc {
构造函数(){
this.helpfulService =新MyFirstSvc();
}
}出口类MyThirdSvc {
构造函数(){
this.helpfulService =新MyFirstSvc();
}
}
是,第一件事是添加你要注入的每个服务 @Injectable
装饰。事实上,注射
名字有点阴险。它并不意味着类将是可注射的,但它会装点这样的构造参数可以注射。详细信息请参见本github上的问题:<一href=\"https://github.com/angular/angular/issues/4404\">https://github.com/angular/angular/issues/4404.
下面是我对注入机制的理解。当设置了 @Injectable
装饰一类,角将尝试创建或获取的实例在喷油器当前执行链对应的类型。事实上,不仅是一个喷射器用于Angular2应用程序,但喷射器的一棵树。它们被隐式关联到整个应用程序和组件。在这个水平的一个重要特点是,它们连接在一起以分层方式。喷射器的这种树映射组件的树。没有注射器是为服务的定义。
让我们一起来样本。我有以下应用:
-
组件
AppComponent
:这是创建在引导$ C $的Angular2应用程序时提供了我的应用程序的主要组成部分C>函数
@Component({
选择:我的应用,
模板:`
&LT;儿童&GT;&LT; /儿童&GT;
`
(......)
指令:[ChildComponent]
})
出口类AppComponent {
} -
组件
ChildComponent
:将在AppComponent
组件中使用的子组件@Component({
选择:'孩子',
模板:`
{{数据| JSON}}&LT; BR /&GT;
&LT; A HREF =#(点击)=的getData()&GT;获取数据与LT; / A&GT;
`
(......)
})
出口类ChildComponent {
构造函数(服务1:服务1){
this.service1 =服务1;
} 的getData(){
this.data = this.service1.getData();
返回false;
}
} -
两个服务,
服务1
和客服2
:服务1
所使用的ChildComponent
和客服2
按服务1
@Injectable()
出口类服务{
构造函数(客服2:客服2){
this.service2 =服务2;
} 的getData(){
返回this.service2.getData();
}
}@Injectable()
出口类服务2 { 的getData(){
返回[
{消息:MESSAGE1},
{消息:消息2'}
];
}
}
下面是所有这些因素有关系的概述:
应用
|
AppComponent
|
ChildComponent
getData()会---服务1 - 服务2
在这样的应用,我们有三个喷油嘴:
- 可以使用
引导
函数的第二个参数来配置应用程序注入 - 可以使用
提供商
此组件的属性来配置的AppComponent
注射器。它可以看到在应用程序中注入定义的元素。这意味着,如果提供者未在此提供程序中,它会自动寻找到这个父注射器。如果后者没有发现,一个供应商未找到错误将被抛出。 - 的
ChildComponent
注射器,将遵循比AppComponent
一个相同的规则。注入参与FORR组件执行注射链组件,运营商将,然后在AppComponent
之一,并最终应用中的一个来寻找第一个在这个注射器。
这意味着,试图注入服务1
到 ChildComponent
构造,Angular2将寻找到<$时C $ C> ChildComponent 注射器,然后进入 AppComponent
之一,最后到应用程序之一。
由于客服2
需要注入服务1
,同样的分辨率处理会做: ChildComponent
喷油器, AppComponent
之一,并应用之一。
这意味着这两个服务1
和客服2
使用根据自己的需要可以在每个级别指定的<$对于组件C $ C>提供商属性和应用喷油器引导
函数的第二个参数。
这允许共享依赖性的实例为一组元素:
- 如果你定义在应用程序级别的供应商,把对应的创建的实例将被整个应用程序中共享(所有组件,所有服务,...)。
- 如果您在组件级别上定义的供应商,该实例将参与依赖链组件本身,它的子组件和所有的服务的共享。
所以这是非常强大的,你可以自由地组织,只要你想和你的需求。
下面是相应的plunkr所以你可以用它玩:<一href=\"https://plnkr.co/edit/PsySVcX6OKtD3A9TuAEw?p=$p$pview\">https://plnkr.co/edit/PsySVcX6OKtD3A9TuAEw?p=$p$pview.
这从Angular2文档链接可以帮助你:<一href=\"https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html\">https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html.
希望它可以帮助你(抱歉长的答案)
蒂埃里
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();
}
}
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.
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
: 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
: a sub component that will be used within theAppComponent
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; } }
Two services,
Service1
andService2
:Service1
is used by theChildComponent
andService2
byService1
@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:
- 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.
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.
Since Service2
needs to be injected into Service1
, the same resolution processing will be done: ChildComponent
injector, AppComponent
one and application one.
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:
- If you define a provider at the application level, the correspoding created instance will be shared by the whole application (all components, all services, ...).
- If you define a provider at a component level, the instance will be shared by the component itself, its sub components and all the "services" involved in the dependency chain.
So it's very powerful and you're free to organize as you want and for your needs.
Here is the corresponding plunkr so you can play with it: https://plnkr.co/edit/PsySVcX6OKtD3A9TuAEw?p=preview.
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
这篇关于什么是注入一个服务到另一个角2(测试版)的最好方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!