Angular2 中的提供者是什么?

What are providers in Angular2?

在 Angular2 组件配置中,providers 是我们可以指定的键之一。这些提供程序是如何定义的以及它们的用途是什么?

@Component({
  ..
  providers: [..],
  ..
})

:

Angular2 文档逐渐成熟但仍然稀少。它目前将 providers 定义为:

An array of dependency injection providers for services that the component requires.

这个递归定义不是很有用。一个更详细的例子解释会很有帮助。

注册注射剂

供应商让 Angular 的 DI 知道可注射物并定义可注射物(服务)的范围。

注入器的层次结构

Angular 的 DI 创建了一个注入器树(parent > child > grandchild >...),类似于你的组件和指令的结构。

每个提供商一个实例

每个注入器都维护提供程序。每个提供者都提供一个可注射实例。

提供商查找

当组件或指令具有依赖项(构造函数参数)时,DI 开始在该组件的注入器中寻找提供者。如果它有一个,它会从该提供者请求实例并注入它。

如果注入器没有请求的密钥(类型)的提供者,那么将访问父注入器,直到根(bootstrap),直到找到提供者并且可以注入它的实例. (如果没有找到提供者,DI 会抛出错误)。

定义可注入实例的范围

这样您就可以定义共享服务的范围,因为 DI 从请求实例的组件开始向上查找,直到找到一个。

是否单例

您提供多少个可注入的位置决定了将创建多少个实例(它们仅在实际请求时实例化)。

如果您想要整个应用程序的单个实例,则仅在根组件处提供 一次 可注入(或使用 bootstrap(AppComponent, [...]),这会导致相同的行为.

如果您想为每个组件 A 创建一个新实例,则将其添加到组件 A 的提供者中。

(更新) NgModule 惰性和非惰性

随着 NgModule 模块的引入,引入了额外的级别。使用非延迟加载模块注册的提供程序在层次结构中位于根组件之上。

延迟加载的模块位于这些组件加载的组件和指令之上。

因为提供程序在创建注入器后是只读的,所以无法将延迟加载模块中的提供程序添加到根注入器。因此,延迟加载的模块有自己的根作用域。

另见

将提供者想象成一个食谱,告诉 angular 如何注入服务。

我们经常在 angular 中这样声明提供者:

providers: [AnyService]

这只是一个简写:

[new Provider(AnyService, {useClass: AnyService})]

两种方法都说:每当有人需要 "AnyService" 时,提供 class "AnyService"

请注意,尽管我在上面的示例中提供了相同的 class,但在另一种情况下我可以这样做。

[new Provider(AnyService, {useClass: AnyServiceCustom})]

但在这两种情况下,构造函数将保持不变:

constructor( private _anyService: AnyService) {
}

为了更好地理解它,您需要了解依赖注入在 Angular 2 中的工作原理,因为提供程序与它直接相关。

这是每个 angular 2 开发人员的必读内容。

https://angular.io/docs/ts/latest/guide/dependency-injection.html?The%20Provider%20class%20and%20provide%20function#!#injector-providers

提供者通常是单例(一个实例)对象,其他对象可以通过依赖注入 (DI) 进行访问。

如果您打算多次使用一个对象,例如,Http服务在不同的组件中,您可以请求该服务的同一个实例(重用)。您可以在 DI 的帮助下通过 提供 对 DI 为您创建的同一对象的引用来做到这一点。

@Component){
  ..
  providers: [Http]
}

..而不是每次都创建新对象:

@Component){}
class Cmp {
  constructor() {
    // this is pseudo code, doens't work
    this.http = new Http(...options);
  }
}

这是一个近似值,但这是 Dependency Injection 背后的总体思路 - 让框架处理可重用对象的创建和维护... Provider 是 Angular 对这些可重用对象(依赖项)的术语。

import { service_name} from '../path';

@Component({

  selector: 'selector_name',     
  templateUrl: './html file name ',
  styleUrls: ['./css file name '],
  providers: [ ./'service_name'];

})
export class AppComponent {

  constructor(private Service_name: service_name) { 
    //enter code here
}

添加@Sasxa 的话,我想指向 Adam Freeman 的 Pro Angular book(第 20 章(使用服务提供者))以获得更好、更清晰、更详细的解释和惊人的示例。

提供商 类 创建和管理 服务对象 第一次 Angular 需要解析依赖项。Providers 用于将 类 作为服务 注册到 angular 模块 。然后,这个服务 类 可以在模块中的自身创建阶段被其他组件使用。

"服务是提供通用功能以支持应用程序中其他构建块(例如指令、组件和管道)的对象。服务的重要之处在于它们提供服务的方式被使用,这是通过称为 依赖注入 的过程进行的。使用服务可以增加 Angular 应用程序的灵活性和可扩展性,但依赖注入可能是一个难以理解的主题。 “ (亲Angular(第20章))

实际上,服务可以通过依赖注入设法将对象分发为服务。

import { Injectable } from "@angular/core";

export enum LogLevel {DEBUG, INFO, ERROR}

    @Injectable()
    export class LogService {
      minimumLevel: LogLevel = LogLevel.INFO;
      logInfoMessage(message: string){
       this.logMessage(LogLevel.INFO, message);
      }
    }

@Component({
     selector: "example",
     templateUrl: "example.component.html"
})
export class exampleComponent {

  constructor(logService: LogService) {};
  //to do impl
}

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ LogService ],
  declarations: [ ExampleComponent],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

提供者只是服务的实例。

您可以创建一次并在所有地方使用它们,也可以创建多个实例。

让我们了解如何在 Angular

中使用它们

所有服务都在 Angular 中注册,但在我们实例化它们之前无法使用它们。所以首先,我们必须实例化服务,我们通过使用提供者来做到这一点。

有两种方法可以实例化服务。第一个是使用 providers array,第二个是使用 providedIn.

第一种方法使用Providers数组

要在全球范围内使用该服务,我们可以将提供程序放在 AppModule 中。通过这样做,该服务的实例被创建并且应用程序中的所有组件或其他服务将使用相同的实例。

import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { NewService } from './newService';

@NgModule({
  declarations: [
    AppComponent
  ],
  providers: [NewService],
  bootstrap: [AppComponent]
})
export class AppModule { }

要在任何特定组件中使用该服务,我们可以将提供程序放在 ComponentModule 中。通过这样做,该服务的新实例被创建并且所有子组件将使用相同的实例(它将覆盖父实例)。

import { Component, OnInit } from '@angular/core';
import { NewService } from './newService';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  providers:[NewService]
})
export class AppComponent implements OnInit {
  constructor(private newService: newService) { }

  ngOnInit() { }
}

注意:如果您将提供程序放在 AppComponent 中,则该应用程序中的所有组件都可以使用该实例,但其他服务将无法访问该实例。要使其他服务也使用相同的实例,请将其放在 AppModule 中。

第二种方法使用providedIn

您可以使用 Injectable 装饰器来实例化任何服务。

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root' | Type<any>
})
export class UserService {
}

如果它是根用户,那么整个应用程序都可以访问该服务。这意味着 Angular 创建该服务的单个实例并且整个应用程序使用相同的实例。

如果只能在特定模块中访问它,我们可以通过为 providedIn

提供模块名称来实现
@Injectable({
   providedIn: AnyModule
})

使用 Injectable 装饰器实例化服务的另一个优点是,如果该服务根本没有在该应用程序的任何地方使用,那么它不会出现在已编译的 Angular 应用程序中.