Angular 服务模块是否仍然需要?
Are Angular Service Modules still required?
在angular文档中,它列出了可以实现的功能模块类型。其中之一是服务模块。
https://angular.io/guide/module-types
在 Angular 的早期版本中,您将创建服务并将其列在服务 NgModule 的提供程序数组中。然后这个 NgModule 将被消费应用程序导入,服务将在应用程序根注入器中提供。
Injectable()
export class MyService {}
NgModule({
providers: [MyService]
})
export class MyServicesModule {}
NgModule({
imports: [MyServicesModule]
})
export class AppModule {}
最新的 Angular 建议是使用 Injectable 注释,您不再需要在提供程序定义中列出它。
Injectable({ providedIn: 'root'})
export class MyService {}
因此创建服务模块有什么意义吗?您是否只是使用上面的注释创建您想要在根注入器中提供的服务,然后直接导入服务 class 并相应地注入?
如果您使用延迟加载的模块,而这些模块的特定服务仅在该模块内提供,则需要服务模块。
您不能在同一模块中提供服务,而该模块的组件会在该模块中注入服务。
所以假设你有一个 MyLazyFeatureModule
@NgModule({
imports: [ ],
providers: [ ],
declarations: [ MyFeatureComponent ],
exports: [ ],
})
export class MyLazyFeatureModule { }
并且您的服务只包含您的功能的逻辑,那么您不能执行以下操作:
Injectable({ providedIn: MyLazyFeatureModule})
export class MyFeatureService {}
你会得到一个周期!
要解决此问题,您需要创建一个特定的服务模块并将该模块导入到功能模块中:
@NgModule({
imports: [ ],
providers: [ ],
declarations: [ ],
exports: [ ],
})
export class MyLazyFeatureServiceModule { }
Injectable({ providedIn: MyFeatureServiceModule})
export class MyFeatureService {}
@NgModule({
imports: [ MyLazyFeatureServiceModule ],
providers: [ ],
declarations: [ MyFeatureComponent ],
exports: [ ],
})
export class MyLazyFeatureModule { }
请看一下 Manfred Steyer 的 this article (three shakable providers why, how and cycles,它详细解释了为什么有一个循环非常深入。
除了该用例之外,如果您仅在 root 中提供服务,则您可能不需要服务模块。您可以创建一个实际上将所有服务集中在一个地方的服务。但也许核心模块也可以做到这一点。由你决定。
单例服务是providedIn: 'root'
利用tree-shaking的服务。
服务文件的位置:
- 在功能模块的 services 文件夹中,您可以将 a.service.ts 文件放在这里
- 对于似乎不属于特定功能模块的服务(例如,许多模块使用的记录器服务),您可以将服务组织到核心文件夹中 without一个core.module.ts。参见 angular doc on coding style guide。
但是,根据具体情况,如果您正在使用 ngrx 存储或类似库,您可能需要 CoreModule 或某些 ServiceModule 将文件(ngrx 模块)导入到那里。参见 angular v6 doc on coding style guide。
P.S。对于共享事物 app-wide,SharedModule 被认为用于管道、指令和组件,但不用于服务。 shared.module.ts 很可能在其 @NgModule 装饰器中没有提供者 属性。参见 angular doc on SharedModule。
这种命名约定的根本原因1 is that the root injector is there for all singleton services (working well for both eager modules and lazy loaded modules), so that you usually don't want to create another injector (unless you know what you're doing, such as the forRoot pattern 2 eg<- 顺便说一句,请记住,如果您已经让所有服务 providedIn: 'root'
,那么就可以避免这样的麻烦。
总而言之,angular 文档建议将所有服务设为单例,并且 tree-shakable 3 4;服务适合 3 个地方:功能模块的 services 文件夹或核心模块/服务模块,尤其是在使用 ngrx 时或仅用于保持服务井井有条的核心文件夹。
相关文档和参考资料
https://angular.io/guide/singleton-services
https://angular.io/guide/providers
https://angular.io/guide/router
https://angular.io/guide/lazy-loading-ngmodules
https://v6.angular.io/guide/styleguide CoreModule 1 3
在angular文档中,它列出了可以实现的功能模块类型。其中之一是服务模块。
https://angular.io/guide/module-types
在 Angular 的早期版本中,您将创建服务并将其列在服务 NgModule 的提供程序数组中。然后这个 NgModule 将被消费应用程序导入,服务将在应用程序根注入器中提供。
Injectable()
export class MyService {}
NgModule({
providers: [MyService]
})
export class MyServicesModule {}
NgModule({
imports: [MyServicesModule]
})
export class AppModule {}
最新的 Angular 建议是使用 Injectable 注释,您不再需要在提供程序定义中列出它。
Injectable({ providedIn: 'root'})
export class MyService {}
因此创建服务模块有什么意义吗?您是否只是使用上面的注释创建您想要在根注入器中提供的服务,然后直接导入服务 class 并相应地注入?
如果您使用延迟加载的模块,而这些模块的特定服务仅在该模块内提供,则需要服务模块。
您不能在同一模块中提供服务,而该模块的组件会在该模块中注入服务。
所以假设你有一个 MyLazyFeatureModule
@NgModule({
imports: [ ],
providers: [ ],
declarations: [ MyFeatureComponent ],
exports: [ ],
})
export class MyLazyFeatureModule { }
并且您的服务只包含您的功能的逻辑,那么您不能执行以下操作:
Injectable({ providedIn: MyLazyFeatureModule})
export class MyFeatureService {}
你会得到一个周期!
要解决此问题,您需要创建一个特定的服务模块并将该模块导入到功能模块中:
@NgModule({
imports: [ ],
providers: [ ],
declarations: [ ],
exports: [ ],
})
export class MyLazyFeatureServiceModule { }
Injectable({ providedIn: MyFeatureServiceModule})
export class MyFeatureService {}
@NgModule({
imports: [ MyLazyFeatureServiceModule ],
providers: [ ],
declarations: [ MyFeatureComponent ],
exports: [ ],
})
export class MyLazyFeatureModule { }
请看一下 Manfred Steyer 的 this article (three shakable providers why, how and cycles,它详细解释了为什么有一个循环非常深入。
除了该用例之外,如果您仅在 root 中提供服务,则您可能不需要服务模块。您可以创建一个实际上将所有服务集中在一个地方的服务。但也许核心模块也可以做到这一点。由你决定。
单例服务是providedIn: 'root'
利用tree-shaking的服务。
服务文件的位置:
- 在功能模块的 services 文件夹中,您可以将 a.service.ts 文件放在这里
- 对于似乎不属于特定功能模块的服务(例如,许多模块使用的记录器服务),您可以将服务组织到核心文件夹中 without一个core.module.ts。参见 angular doc on coding style guide。
但是,根据具体情况,如果您正在使用 ngrx 存储或类似库,您可能需要 CoreModule 或某些 ServiceModule 将文件(ngrx 模块)导入到那里。参见 angular v6 doc on coding style guide。
P.S。对于共享事物 app-wide,SharedModule 被认为用于管道、指令和组件,但不用于服务。 shared.module.ts 很可能在其 @NgModule 装饰器中没有提供者 属性。参见 angular doc on SharedModule。
这种命名约定的根本原因1 is that the root injector is there for all singleton services (working well for both eager modules and lazy loaded modules), so that you usually don't want to create another injector (unless you know what you're doing, such as the forRoot pattern 2 eg<- 顺便说一句,请记住,如果您已经让所有服务 providedIn: 'root'
,那么就可以避免这样的麻烦。
总而言之,angular 文档建议将所有服务设为单例,并且 tree-shakable 3 4;服务适合 3 个地方:功能模块的 services 文件夹或核心模块/服务模块,尤其是在使用 ngrx 时或仅用于保持服务井井有条的核心文件夹。
相关文档和参考资料
https://angular.io/guide/singleton-services
https://angular.io/guide/providers
https://angular.io/guide/router
https://angular.io/guide/lazy-loading-ngmodules
https://v6.angular.io/guide/styleguide CoreModule 1