首页 > 解决方案 > 在其他多个延迟加载模块之间共享延迟加载(不在 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.moduleApp.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 { ... }

然后我们有这两个懒惰的:adminmain.

如果我要这样导入SecurityModule

@NgModule({
    imports: [
        SecurityModule
    ]
})
export class MainModule { }

我最终会AuthenticationService为 Main 和 Admin 分开。如果我将它导入App.module,确保它可以工作,但我必须加载 HUGE SecurityModule,当它只需要在 Main/Admin 中可能永远不会被访问时。

标签: angulartypescriptlazy-loadingangular8

解决方案


到目前为止,所有答案都是非常酷的读物(即使在发布问题之前我实际上已经阅读了大量的答案)。

(我认为所有建议的链接)的问题forRoot是(对我而言)它不是真正的 DI,因为它与注入的模块/服务紧密App.module结合 - 这是我在问题中描述的整个问题。

因为我是一个头脑清醒的 Java 编码器(而且我们确实喜欢依赖注入),所以我无法动摇必须有办法让它成为真正的 DI 的想法。

所以我很确定Shashank Vivek在这里至少部分错误:

因为这是使它在 Angular 中工作的唯一方法

很难找到一个好的解决方案的原因是因为 Angular 是该死的快速开发框架,你发现的几乎 90% 的内容都在 2-4 版本左右。

无论如何 - 从 Angular 6 开始,我们在装饰器中提供了 In,虽然它已经为我所知好几个月了(因为与 forRoot 相比,它被认为是“真正的 DI”),但它让我感到惊讶:它实际上是可摇树的

总而言之-您可以从字面上获取一项服务,用providedIn标记它,而不是在您实际使用它的地方之外的任何地方(实际上没有声明或导入)。

事实证明服务是它们自己的生物,Angular 足够聪明,可以用任何使用它们的东西来加载和打包它们。

所以我的问题的答案是:

  1. 删除所有和任何对惰性服务的引用。
  2. @Injectable({ providedIn: 'root' })
  3. 只需将它们注入到您需要它们的构造函数中(在延迟加载的模块中)。

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 ...深埋在有角的文档中。

这是一个演示代码来玩它!


推荐阅读