javascript - Angular 2 - 服务 - 来自另一个服务的依赖注入(inject)

标签 javascript dependency-injection dependencies angular

我在 Angular 2 中编写了两个服务。其中之一是一个基本的、自定义的 Http 类,其中包含一些自定义功能(目前看起来很基本,但它将不断扩展):

ServerComms.ts

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';

@Injectable()
export class ServerComms {
    private url = 'myservice.com/service/';

    constructor (public http: Http) {
        // do nothing
    }

    get(options) {
        var req = http.get('https://' + options.name + url);

        if (options.timout) {
            req.timeout(options.timeout);
        }

        return req;
    }
}

另一个类,TicketService 利用上面的此类,并调用服务中的方法之一。定义如下:

TicketService.ts

import {Injectable} from 'angular2/core';
import {ServerComms} from './ServerComms';

@Injectable()
export class TicketService {
    constructor (private serverComms: ServerComms) {
        // do nothing
    }

    getTickets() {
        serverComms.get({
            name: 'mycompany',
            timeout: 15000
        })
            .subscribe(data => console.log(data));
    }
}

但是,每当我尝试此操作时,我都会收到以下错误:

"No provider for ServerComms! (App -> TicketService -> ServerComms)"

我不明白为什么?我当然不需要注入(inject)每个其他服务所依赖的每个服务吗?这会变得相当乏味吗?这在 Angular 1.x 中是可以实现的 - 我如何在 Angular 2 中实现同样的效果?

这是正确的方法吗?

最佳答案

简而言之,由于注入(inject)器是在组件级别定义的,因此发起调用服务的组件必须看到相应的提供者。第一个(直接调用),但也间接调用另一个(由前一个服务调用)。

我们来举个例子。我有以下应用程序:

  • 组件 AppComponent :我的应用程序的主要组件,在 bootstrap 中创建 Angular2 应用程序时提供。功能

    @Component({
      selector: 'my-app', 
        template: `
          <child></child>
        `,
        (...)
        directives: [ ChildComponent ]
    })
    export class AppComponent {
    }
    
  • 组件 ChildComponent :将在 AppComponent 中使用的子组件组件

    @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 使用和Service2通过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' }
        ];
      }
    }
    

以下是所有这些元素及其关系的概述:

Application
     |
AppComponent
     |
ChildComponent
  getData()     --- Service1 --- Service2

在这样的应用程序中,我们有三个注入(inject)器:

  • 可以使用 bootstrap 的第二个参数进行配置的应用程序注入(inject)器功能
  • AppComponent可以使用 providers 配置注入(inject)器该组件的属性。它可以“查看”应用程序注入(inject)器中定义的元素。这意味着如果在此提供程序中找不到提供程序,它将自动在该父注入(inject)器中查找。如果后者没有找到,则会抛出“未找到提供者”错误。
  • ChildComponent喷射器将遵循与 AppComponent 相同的规则一。要注入(inject)为组件执行的注入(inject)链中涉及的元素,将首先在此注入(inject)器中查找提供程序,然后在 AppComponent 中查找提供程序。第一个,最后是应用程序中的一个。

这意味着当尝试注入(inject)Service1时进入ChildComponent构造函数中,Angular2 将查看 ChildComponent注入(inject)器,然后进入AppComponent一,最后进入应用程序一。

Service2需要注入(inject)Service1 ,将进行相同的分辨率处理:ChildComponent喷油器,AppComponent一和应用一。

这意味着Service1Service2可以根据您的需要使用providers在每个级别指定组件的属性和 bootstrap 的第二个参数应用程序注入(inject)器的函数。

这允许共享一组元素的依赖关系实例:

  • 如果您在应用程序级别定义提供程序,则相应创建的实例将由整个应用程序(所有组件、所有服务……)共享。
  • 如果您在组件级别定义提供程序,则该实例将由组件本身、其子组件以及依赖链中涉及的所有“服务”共享。

所以它非常强大,您可以根据自己的需要自由地进行组织。

这是相应的 plunkr,您可以使用它:https://plnkr.co/edit/PsySVcX6OKtD3A9TuAEw?p=preview .

Angular2 文档中的此链接可以帮助您:https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html .

关于javascript - Angular 2 - 服务 - 来自另一个服务的依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36651739/

相关文章:

javascript - 如何使用 TypeScript 将单独文件中的两个类合并到一个 ES6 模块中?

javascript - express.js 在终端中获取 json 文件

php - 避免在构造函数服务 Symfony 中使用长参数列表

android - 错误 : cannot find symbol method getMap() after dependencies update

javascript - 如何提高指定高度(DOM 操作)的性能?

javascript - 如何迭代 javascript 数组并调用更新同一数组的函数?

android - 我可以对 Koin 模块进行单元测试吗?

java - Java EE 中的@Producer 注解

dependencies - 什么是发布火车 Bom?

c++ - protobuf c++ 还依赖哪些其他库来编译运行时?