Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/457.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Angular 2-来自另一个服务的服务依赖项注入_Javascript_Dependency Injection_Dependencies_Angular - Fatal编程技术网

Javascript Angular 2-来自另一个服务的服务依赖项注入

Javascript Angular 2-来自另一个服务的服务依赖项注入,javascript,dependency-injection,dependencies,angular,Javascript,Dependency Injection,Dependencies,Angular,我在Angular 2中写了两个服务。其中之一是一个基本的、自定义的Http类,其中包含一些自定义功能,目前看来是基本的,但它将不断扩展: 服务器通信 另一个类TicketService使用上面的这个类,并调用服务中的一个方法。其定义如下: 票务服务 但是,每当我尝试此操作时,都会收到以下错误: "No provider for ServerComms! (App -> TicketService -> ServerComms)" 我不明白为什么?当然,我不需要注入彼此服务所依赖的

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

服务器通信

另一个类TicketService使用上面的这个类,并调用服务中的一个方法。其定义如下:

票务服务

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

"No provider for ServerComms! (App -> TicketService -> ServerComms)"
我不明白为什么?当然,我不需要注入彼此服务所依赖的每个服务?这会变得很乏味吗?这在Angular 1.x中是可以实现的-如何在Angular 2中实现同样的效果

这是正确的方法吗?

你当然知道

在Angular2中,有多个喷油器。使用提供程序组件阵列配置喷油器。当组件具有提供者阵列时,将在树中的该点创建注入器。当组件、指令和服务需要解决它们的依赖关系时,它们会查找注入器树以找到它们。因此,我们需要使用提供者配置该树

从概念上讲,我喜欢认为有一个注入器树覆盖在组件树上,但它比组件树更稀疏

同样,在概念上,我们必须配置此注入器树,以便在树中的适当位置提供依赖项。Angular 2没有创建单独的树,而是重用组件树来执行此操作。因此,尽管感觉我们是在组件树上配置依赖项,但我喜欢认为我是在注入器树上配置依赖项,注入器树恰好覆盖了组件树,因此我必须使用组件来配置它

清澈如泥

Angular two拥有注入器树的原因是允许非单例服务,即能够在注入器树中的不同点创建特定服务的多个实例。如果您只想要Angular 1-like功能的单例服务,请在根组件中提供所有服务


构建应用程序,然后返回并使用组件配置注入器树。我喜欢这样想。如果在另一个项目中重用组件,则很可能需要更改提供程序阵列,因为新项目可能需要不同的注入器树。

简而言之,由于注入器是在组件级别定义的,因此启动呼叫服务的组件必须看到相应的提供程序。第一个被直接调用,但另一个被前一个服务间接调用

我们来取样吧。本人有以下申请:

Component AppComponent:在引导函数中创建Angular2应用程序时提供的我的应用程序的主要组件

两个服务,Service1和Service2:Service1由ChildComponent使用,Service2由Service1使用

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

Application
     |
AppComponent
     |
ChildComponent
  getData()     --- Service1 --- Service2
在这种应用中,我们有三个喷油器:

可以使用引导功能的第二个参数配置的应用程序注入器 AppComponent注入器,可使用此组件的providers属性进行配置。它可以看到应用程序中定义的元素。这意味着,如果在此提供程序中找不到提供程序,将自动在此父注入器中查找该提供程序。如果在后者中找不到,将抛出“未找到提供程序”错误。 子组件注入器将遵循与AppComponent注入器相同的规则。为了注入为组件执行的注入链中所涉及的元素,将首先在该注入器中查找提供者,然后在AppComponent中查找提供者,最后在应用程序中查找提供者。 这意味着,当尝试将Service1注入ChildComponent构造函数时,Angular2将查看ChildComponent注入器,然后查看AppComponent注入器,最后查看应用程序注入器

由于Service2需要注入Service1,因此将执行相同的解析处理:childcomponentinjector、appcomponentone和applicationone

这意味着可以使用组件的providers属性和应用程序的bootstrap函数的第二个参数,根据需要在每个级别指定Service1和Service2

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

如果在应用程序级别定义提供程序,则创建的相应代码实例将由整个应用程序所有组件、所有服务等共享。。。。 如果在组件级别定义提供者,则该实例将由组件本身、其子组件以及依赖关系链中涉及的所有服务共享。 所以它非常强大,你可以根据自己的需要自由组织

这是对应的plunkr so 你可以玩它:


Angular2文档中的此链接可以帮助您:。

好吧,我想您应该在全球范围内提供这两种服务:

bootstrap(App, [service1, service2]);
或提供给使用它们的组件:

@Component({providers: [service1, service2]})
@可注入装饰器添加必要的元数据来跟踪依赖项,但不提供它们

@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; 
  }
}
@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
bootstrap(App, [service1, service2]);
@Component({providers: [service1, service2]})