Angular Service Modules是否仍然需要?

28 浏览
0 Comments

Angular Service Modules是否仍然需要?

在Angular文档中,列出了可以实现的功能模块的类型,其中之一是服务模块。在早期版本的Angular中,您需要创建您的服务并将其列在服务NgModule的providers数组中。然后,使用该NgModule的应用程序将导入并在应用程序根注入器中提供该服务。

@Injectable()

export class MyService {}

@NgModule({

providers: [MyService]

})

export class MyServicesModule {}

@NgModule({

imports: [MyServicesModule]

})

export class AppModule {}

最新的Angular推荐使用@Injectable注解,您不再需要在providers定义中列出它。

@Injectable({ providedIn: 'root'})

export class MyService {}

因此,是否有必要创建服务模块?您只需使用上述注解在根注入器中创建要提供的服务,并直接导入和注入服务类即可。

0
0 Comments

在Angular中,一个单例服务是指通过providedIn: 'root'来提供的服务,以便利用树摇优化机制。单例服务的位置有以下几种情况:

- 如果一个服务文件位于特性模块的services文件夹中,可以将服务文件放在这里。

- 对于一些不属于特定特性模块的服务(例如多个模块都使用的日志服务),可以将服务组织到一个没有core.module.ts的核心文件夹中。详情请参考Angular的编码风格指南

然而,根据具体情况,如果你在使用ngrx store或类似的库,可能需要一个CoreModule或一些ServiceModule来导入这些文件(ngrx模块)。详情请参考Angular v6的编码风格指南

P.S. 如果要在整个应用中共享东西,可以考虑使用SharedModule来共享管道、指令和组件,但不适用于服务。在shared.module.ts中,可能没有providers属性的装饰器。详情请参考Angular的SharedModule文档

总结一下,Angular文档推荐将所有服务设为单例且可树摇优化;服务可以放在以下三个位置:特性模块的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

- https://zhuanlan.zhihu.com/p/63515048#%E5%A6%82%E4%BD%95%E6%9B%B4%E5%A5%BD%E5%9C%B0%E7%BB%84%E7%BB%87Angular%E9%A1%B9%E7%9B%AE

- https://stackoverflow.com/questions/42695931/42696386#42696386

- https://github.com/ng-alain/ng-alain/issues/180

- https://angular.io/guide/module-types

0
0 Comments

Angular Service Modules是否仍然需要?

在使用懒加载模块时,如果模块中的组件只提供特定的服务,那么就需要一个服务模块。

你不能将服务提供给与该模块的组件注入的模块相同的模块中。

所以假设你有一个MyLazyFeatureModule

({
  imports:      [ ],
  providers:    [ ],
  declarations: [ MyFeatureComponent ],
  exports:      [ ],
})
export class MyLazyFeatureModule { }

还有一个只包含与你的功能相关逻辑的服务,那么你不能这样做:

Injectable({ providedIn: MyLazyFeatureModule})
export class MyFeatureService {}

你会得到一个循环依赖的错误!

要解决这个问题,你需要创建一个特定的服务模块并将其导入到功能模块中:

({
  imports:      [ ],
  providers:    [ ],
  declarations: [ ],
  exports:      [ ],
})
export class MyLazyFeatureServiceModule { }

Injectable({ providedIn: MyFeatureServiceModule})
export class MyFeatureService {}

({
  imports:      [ MyLazyFeatureServiceModule ],
  providers:    [ ],
  declarations: [ MyFeatureComponent ],
  exports:      [ ],
})
export class MyLazyFeatureModule { }

请查看这篇文章 (three shakable providers why, how and cycles),由Manfred Steyer详细解释了为什么会出现循环依赖的问题。

除此之外,如果你只在根目录下提供服务,那么可能不需要服务模块。你也可以创建一个核心模块来集中所有的服务。这取决于你的需求。

如果不打算导入服务模块,那么我认为没有必要创建一个模块,这似乎是多余的。你能解释一下你所说的核心模块是什么意思吗?

你必须将服务模块导入到功能模块中。我将在我的回答中添加一个结构概述,或许这样会更清楚一些。

更新了我的回答,希望现在更清楚了为什么需要这个服务模块。

谢谢你的帮助。我试着访问你提供的链接,但是我不太理解它想要传达的意思。上面的MyFeatureModule是打算在懒加载的上下文中使用的吗?如果是这样,也许更新模块的名称来包含“Lazy”这个词会更好。你能解释一下你在第一个例子中提到的循环是指什么吗?

是的,大部分情况下都是这样的用例。你有一个懒加载的功能模块,并且你希望将服务限定在该范围内,以便服务只被捆绑在懒加载模块中,而不是主应用程序中。如果你想实现这一点,你需要添加一个服务模块。

好的,非常感谢!我理解你在谈论作用域的问题。但是对于循环依赖的参考,我仍然感到困惑!

我们可以创建一个服务模块。我知道我们可以在模块的'providers'数组中注册一个服务({}),或者在({})中注册一个服务。创建一个名为MyFeatureServiceModule的服务模块意味着什么?

循环发生的原因是,当编译器尝试创建模块时,它会遍历组件并创建组件中注入的服务的实例(如果不存在)。当编译器遇到一个服务,它的providedIn与它当前正在尝试创建的模块相同时,编译器会进入循环,因为它需要创建服务以创建模块,但也需要模块来创建服务。

服务模块是一种将服务分组到自己的功能相关模块中的模式,使得路由模块更易读,因为提供者列表不会那么长。这里的问题是,随着树摇动的提供者引入(providedIn声明),这种模式是否已经过时,或者是否仍然有用的用例。

如果我有一个名为'myService.ts'的服务,其中包含名为'myServiceClass'的类,并且想要将实例注入到名为'myFeatureModule.module.ts'的功能模块中,其中包含名为'myFeatureModule'的类。我不能像这样注册'myService.ts':({ providedIn: 'myFeatureModule' }),就像我们使用({ providedIn: 'root' })一样吗?我认为我们也可以像这样做。基本上,'providedIn'只是注册服务的一种简便方式。 stackoverflow.com/questions/50848357/…

没有人说过你不能只使用提供者列表,或者必须使用服务模块。树摇动的声明(providedIn)不仅仅是一个简化,而是为了使未使用的代码部分的树摇动更加高效。在官方的Angular文档和我在回答中提供的链接中有大量的解释,如果你想要了解更多的话。所以选择哪种方式取决于具体的用例...

非常好的信息。现在更加清晰了。我的唯一建议是更新你的示例模块类名称,以包含"Lazy"一词,以提高其他人的理解能力。

0