在另一个提供者Angular 2上注入提供者

时间:2016-02-10 22:57:07

标签: typescript angular

假设我们有一个名为 Comp 的组件和两个名为 P1 P2 的@Injectable提供商。

P1 需要 P2 的实例。

Comp

上注入

P1

如果我在 Comp 上声明两个提供商,那就完美了,就像那样:

docker run -v /postgres/storage:/container/postgres --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres

现在我想做的是直接在 P1 内声明 P1 需要 P2

@Component ({
    providers: [P1, P2]
})
export class Comp { ... }

感谢您的帮助。

5 个答案:

答案 0 :(得分:13)

实际上,注入器只能配置组件级别或引导应用程序。

当您将提供程序设置为组件级别时,处理中涉及的每个类都可以访问这些提供程序:子组件,服务。但是,您无法自行配置服务提供商。

如果在引导级别配置提供程序(调用bootstrap函数时),则应用程序中的所有元素都可以使用这些提供程序。

事实上,Angular2的依赖注入器利用了分层注入器。这意味着提供者未在某个级别找到,它将在上面的级别查找,依此类推。

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

Application
(providers defined in bootstrap)
     |
AppComponent
(providers defined in the providers attribute)
     |
ChildComponent
(providers defined in the providers attribute)
  getData()     --- Service1 --- Service2

为了能够在Service2中使用Service1,必须在提供程序树中找到相应的提供程序。

在这种应用中,我们有三个注射器:

  • 可以使用bootstrap函数
  • 的第二个参数配置的应用程序注入器
  • 可以使用此组件的AppComponent属性配置的providers注入器。它可以"看"应用程序注入器中定义的元素。这意味着如果在此提供程序中找不到提供程序,它将自动查找此父注入程序。如果在后者中找不到,则找不到"提供商"错误将被抛出。
  • ChildComponent注入器遵循与AppComponent规则相同的规则。要注入为组件执行的注入链中涉及的元素,将首先在此注入器中查找提供者,然后在AppComponent中查找提供者,最后在应用程序中查找提供者。

这个答案可以为您提供有关分层注入器的更多详细信息:

答案 1 :(得分:3)

您有两种选择:

  1. 正如其他答案所述,您必须将服务放在组件的providers数组中,就像您一样:

    providers: [P1, P2]
    

    P1的构造函数中只需注入它:

    export class P1 {
        constructor(private p2: P2){}
    }
    
  2. 如果您不想将其放在providers数组中,可以使用引导主要组件的bootstrap方法执行此操作:

    bootstrap(AppComponent, [P2]);
    
  3. 再次,只需在P1

    中以相同的方式注入它

    我不推荐第二个,而Angular 2的创作者也不推荐它。如果您希望在任何地方都可以使用全局服务(在其他服务和组件中,只需将其放在根组件的providers数组中)

    来源:https://angular.io/docs/ts/latest/guide/dependency-injection.html

      

    我们必须通过注册在我们的应用程序中创建所需服务的提供程序来配置注入器。我们将在本章后面解释哪些提供程序。在我们开始之前,让我们看一下在引导期间提供者注册的示例:

         

    // Injecting services in bootstrap works but is discouraged

         

    bootstrap(AppComponent, [HeroService]);

         

    注射器现在知道我们的HeroService。我们的HeroService实例将在整个应用程序中注入。

         

    当然,我们无法对这条评论告诉我们不要感到疑惑   这样做。它会工作。这不是最好的做法。该   bootstrap provider选项用于配置和覆盖   Angular自己的预注册服务。

         

    首选方法是注册应用程序提供商   应用组件。因为HeroService将在其中使用   英雄的特色区域 - 其他地方 - 是理想的地方   注册它是在顶级HeroesComponent。

答案 2 :(得分:1)

Injectables通过构造函数注入以与组件相同的方式支持依赖注入。

@Injectable()
export class P1 {
    constructor(private p2: P2){}
}

您可以通过将其添加到引导程序

将其声明为整个应用程序可用的提供程序
bootstrap(MyAppComponent, [P1, P2, ...]);

答案 3 :(得分:1)

这是一个未解决的问题

https://github.com/angular/angular/issues/5622

这似乎不太可能实现: - /

目前,提供者只能在组件/指令/管道和bootstrap()中声明。组件/指令/管道的提供者的限制是它们不能在全局配置中被覆盖。

答案 4 :(得分:1)

你可以这样做:

string_input_producer

您可能还需要创建自己的RxJS obserwable以从P2返回已处理的数据。在此查看详细信息:https://egghead.io/lessons/rxjs-creating-an-observable