angular - 在其他多个延迟加载模块之间共享延迟加载(不在 App.module 中)服务(DI 上下文)?
问题描述
让我们来看一个场景:
App.module
|__Lazy1.module
| \__LazyService1.module
|__Lazy2.module
| \__LazyService1.module
\__(many more)
目标是为LazyService1.module
提供单例实例Lazy1/2.module
,但仅在获取 Lazy1/Lazy2 时才需要加载。
Angular 只创建和解析根 DI 上下文一次。任何后续上下文(对于惰性模块)都是子上下文。我的问题是我不想LazyService1.module
在App.module
(它是一个大模块,仅由 2 个延迟加载的模块使用)中提供服务(),所以从逻辑上讲,我LazyService1.module
不会在根 DI 上下文中解决。
我需要以某种方式在 2 个延迟加载的模块之间共享 DI 上下文,而不必使其成为根依赖项(in App.module
)。
有没有办法定义共享 DI?一个模块可以访问其他模块的 DI 上下文吗?
是否可以在 root 中提供延迟加载服务以供其他延迟加载模块使用,而无需从 root 提供App.module
?
至于堆栈 - 我不认为我可以提供堆栈,因为我不知道它的外观。我可以实现一个急切地在 root 中提供服务的服务,但这不是这里的问题。
编辑2:
应用程序模块:
@NgModule({
declarations: [
AppComponent,
],
imports: [
// Used by all:
BrowserModule,
BrowserAnimationsModule,
CommonModule,
HttpClientModule,
// App router:
AppRoutingModule
],
bootstrap: [AppComponent]
})
export class AppModule { }
延迟加载路由模块:
const routes: Routes = [
{ path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) },
{ path: 'main', loadChildren: () => import('./main/main.module').then(m => m.MainModule) },
... many others, lazy or not
];
服务模块:
@NgModule({
providers: [
AuthenticationService
],
declarations: [...],
exports: [...],
imports: [
CommonModule,
]
})
export class SecurityModule { }
服务:
@Injectable()
export class AuthenticationService { ... }
然后我们有这两个懒惰的:admin
和main
.
如果我要这样导入SecurityModule
:
@NgModule({
imports: [
SecurityModule
]
})
export class MainModule { }
我最终会AuthenticationService
为 Main 和 Admin 分开。如果我将它导入App.module
,确保它可以工作,但我必须加载 HUGE SecurityModule
,当它只需要在 Main/Admin 中可能永远不会被访问时。
解决方案
到目前为止,所有答案都是非常酷的读物(即使在发布问题之前我实际上已经阅读了大量的答案)。
(我认为所有建议的链接)的问题forRoot
是(对我而言)它不是真正的 DI,因为它与注入的模块/服务紧密App.module
结合 - 这是我在问题中描述的整个问题。
因为我是一个头脑清醒的 Java 编码器(而且我们确实喜欢依赖注入),所以我无法动摇必须有办法让它成为真正的 DI 的想法。
所以我很确定Shashank Vivek在这里至少部分错误:
因为这是使它在 Angular 中工作的唯一方法
很难找到一个好的解决方案的原因是因为 Angular 是该死的快速开发框架,你发现的几乎 90% 的内容都在 2-4 版本左右。
无论如何 - 从 Angular 6 开始,我们在装饰器中提供了 In,虽然它已经为我所知好几个月了(因为与 forRoot 相比,它被认为是“真正的 DI”),但它让我感到惊讶:它实际上是可摇树的!
总而言之-您可以从字面上获取一项服务,用providedIn标记它,而不是在您实际使用它的地方之外的任何地方(实际上没有声明或导入)。
事实证明服务是它们自己的生物,Angular 足够聪明,可以用任何使用它们的东西来加载和打包它们。
所以我的问题的答案是:
- 删除所有和任何对惰性服务的引用。
- 用
@Injectable({ providedIn: 'root' })
- 只需将它们注入到您需要它们的构造函数中(在延迟加载的模块中)。
Angular 将制作部分惰性模块,其中包含在许多惰性模块之间共享的服务(和其他东西)(如我的示例中),并在加载它们时加载它们。该实例将在根目录(在我的情况下)中提供并在所有应用程序(惰性模块)之间共享。
更进一步(因为 DI 是爱),这里有一本很好的读物,关于如何让事情更进一步(我说的是 Spring 级别的更远)。:)
https://angular.io/guide/dependency-injection-providers#tree-shakable-providers
https://www.softwarearchitekt.at/aktuelles/the-new-treeshakable-providers-api-in-angular/
我很惊讶这很难找到:O ...深埋在有角的文档中。
推荐阅读
- c# - Entity Framework Core 3 Preview 7 - 包括 Where 中使用的属性所必需的
- java - Webview 设置 overrideurl 未使用
- swift - Swift 日期组件 .day 被忽略
- vue.js - Vue:为什么我不能在组件模板中使用 refs?
- python - 如何在 python 3.6 中整齐地打印一长串数字?
- python - 为了在 django 中为管理站点提供自定义字符串表示,我需要在模型或字段中覆盖什么?
- c++ - std::min - 设计考虑
- r - 函数返回的 ggplot 对象打印空白图
- c# - 为什么 float.Parse("123,45") 不抛出异常
- c# - 如何使用键在天空盒之间切换?