什么是注入一个服务到另一个角2(测试版)的最好方法? [英] What's the best way to inject one service into another in angular 2 (Beta)?

查看:292
本文介绍了什么是注入一个服务到另一个角2(测试版)的最好方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道如何注入到服务(通过@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 :这是创建在引导函数

      @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 the bootstrap function

    @Component({
      selector: 'my-app', 
        template: `
          <child></child>
        `,
        (...)
        directives: [ ChildComponent ]
    })
    export class 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; 
      }
    }
    

  • 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:

  • The application injector that can be configured using the second parameter of the bootstrap function
  • The AppComponent injector that can be configured using the providers 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 the AppComponent one. To inject elements involved in the injection chain executed forr the component, providers will be looked for first in this injector, then in the AppComponent 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆