在 angular 2 (Beta) 中将一项服务注入另一项服务的最佳方法是什么? [英] What's the best way to inject one service into another in angular 2 (Beta)?

查看:25
本文介绍了在 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 the bootstrap 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; 
      }
    }
    

  • 两个服务,Service1Service2:Service1ChildComponent 使用>Service2Service1

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

    这意味着当尝试将 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.

    这意味着 Service1Service2 都可以根据您的需要使用组件的 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屋!

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