在Angular 6中生成Services时,使用Injectable装饰器提供ProvideIn的目的是什么?


136

在Angular CLI中生成服务时,它将为Injectable装饰器添加带有“提供的”属性且默认值为“ root”的额外元数据。

@Injectable({
  providedIn: 'root',
})

ProvideIn到底做什么?我假设这使服务像整个应用程序的“全局”类型单例服务一样可用,但是,在AppModule的提供程序数组中声明这样的服务会更干净吗?

更新:

对于其他任何人,以下段落也对此提供了另一个很好的解释,特别是如果您只想为功能模块提供服务。

现在有一种推荐的新方法,可以@Injectable()使用new providedIn 属性在装饰器内部直接注册提供程序。它接受'root'作为值或您的应用程序的任何模块。使用时'root',您injectable将在应用程序中注册为单例,而无需将其添加到根模块的提供者中。同样,如果使用 providedIn: UsersModuleinjectable注册为的提供者,UsersModule而不会将其添加到providers模块的。” -https://blog.ninja-squad.com/2018/05/04/what-is-new-angular -6 /

更新2:

经过进一步调查,我认为只有 providedIn: 'root'

如果要provide在根模块以外的任何模块中使用服务,则最好使用providers功能模块装饰器中的数组,否则将遇到循环依赖关系。这里有趣的讨论-https: //github.com/angular/angular-cli/issues/10170


17
我认为您的更新应该是一个答案(您可以回答自己的问题),而不是将其添加到您的问题中。
PhoneixS

最重要的部分是SINGLETON,没人提到!
凯尔·伯凯特

Answers:


54

如果使用provideIn,则将可注射对象注册为模块的提供者,而不将其添加到模块的提供者中。

Docs

服务本身是CLI生成的类,并用@Injectable装饰。默认情况下,此装饰器配置有ProvideIn属性,该属性创建服务的提供程序。在这种情况下,providerIn:'root'指定应在根注入器中提供服务。


4
感谢Sajeetharan。好的,这听起来像是指定应在何处提供服务的新快捷方式。我想我最初的偏好是查看模块的提供程序列表以查看所有声明为提供程序的服务,而不是仔细阅读ProvidedIn标签的分散代码库....(?)
Stefan Zvonar

2
Angular是否有任何理由要添加此内容?这有解决的问题吗?我不认为这是有原因的。
prolink007 '18

3
将AppModule / CoreModule的定义保持较小;)
Stefan Zvonar '18

22
@ prolink007。使用providerIn可以使应用延迟加载服务。要对此进行测试,请将控制台日志放入您的服务中。我的主页曾经加载16个服务,现在却加载了9个。很难量化性能,但是我更好地知道,直到需要它们时才加载服务:)。
Stevethemacguy

3
通过使用providedIn属性定义使用@Injectable()装饰器时应在何处初始化服务,可以使服务可摇晃。然后应将其从NgModule声明的providers属性及其导入语句中删除。这可以通过从捆绑中删除未使用的代码来减小捆绑的大小。
nircraft '19

48

providedIn: 'root' 自Angular 6以来,这是最简单,最有效的服务提供方式:

  1. 该服务将在应用程序范围内以单例形式提供,而无需将其添加到模块的provider数组中(例如Angular <= 5)。
  2. 如果该服务仅在延迟加载的模块中使用,则它将与该模块一起延迟加载
  3. 如果从不使用,它将不会包含在构建中(摇动的树)。

有关更多信息,请考虑阅读文档NgModule常见问题解答

顺便说一句:

  1. 如果您不希望在应用程序范围内使用单例,请使用提供程序的组件数组。
  2. 如果要限制范围,以至于没有其他开发人员会在特定模块之外使用您的服务providers,请改为使用NgModule数组。

37

从文档

什么是可注射装饰器?

将一个类标记为可用于Injector进行创建。

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

@Injectable({
  providedIn: 'root',
})
export class UserService {
}

服务本身是CLI生成的类,并用@Injectable()装饰。

ProvideIn到底做什么?

通过将其与@NgModule或其他InjectorType相关联,或通过指定应在“根”注入器中提供此注入物来确定哪些注入器将提供可注入物,“根”注入器将在大多数应用程序中成为应用程序级注入器。

providedIn: Type<any> | 'root' | null

providerIn:'root'

当您在根级别提供服务时,Angular会创建一个共享的服务实例,并将其注入到任何需要该服务的类中。在@Injectable()元数据中注册提供程序还允许Angular通过从未编译的应用程序中删除服务来优化应用程序。

includedIn:模块

也可以指定应在特定的@NgModule中提供服务。例如,如果您不希望应用程序使用服务,除非它们导入您创建的模块,则可以指定应在模块中提供服务

import { Injectable } from '@angular/core';
import { UserModule } from './user.module';

@Injectable({
  providedIn: UserModule,
})
export class UserService {
}

此方法是首选方法,因为它可以进行树状摇动(树状摇动是构建过程中的一个步骤,该过程将从代码库中删除未使用的代码如果没有注入它,)。

如果无法在服务中指定哪个模块应提供该服务,则还可以在模块内声明该服务的提供者:

import { NgModule } from '@angular/core';
import { UserService } from './user.service';

@NgModule({
  providers: [UserService],
})
export class UserModule {
}

4
最好的解释。
NOP

2
这个答案比角度文档中的定义更好。非常清楚。
Shameera Anuranga

2
很好解释,非常感谢!
扎基·穆罕默德

当它为空时,该@Injectable()怎么办?
Ben Taliadoros

13

includedIn告诉Angular根注入器负责创建您的Service实例。通过这种方式提供的服务会自动提供给整个应用程序使用,不需要在任何模块中列出。

服务类可以充当自己的提供者,这就是为什么在@Injectable装饰器中定义它们是您需要的所有注册的原因。


4

根据Documentation

在@Injectable()元数据中注册提供程序还允许Angular通过从未编译的应用程序中删除服务来优化应用程序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.