惰性加载模块可以共享其父级提供的相同服务实例吗?

Can lazy-loaded modules share the same instance of a service provided by their parent?

我刚刚 运行 遇到一个延迟加载模块的问题,其中父模块和子模块都需要相同的服务,但各自创建一个实例。两者的声明相同,即

import { MyService } from './my.service';
...
@NgModule({
   ...
   providers: [
      MyService,
      ...
   ]
});

这是路由设置

export parentRoutes: Routes = [
   { path: ':id', component: ParentComponent, children: [
      { path: '', component: ParentDetailsComponent },
      { path: 'child', loadChildren: 'app/child.module#ChildModule' },
      ...
   ]}
];

当然,然后在父模块中导入为

RouterModule.forChild(parentRoutes)

如果我想共享同一个服务实例,我该怎么做?

使用 forRoot,如前所述 ,可能是您所需要的。它要解决的问题与您在延迟加载模块获得自己的服务时遇到的问题直接相关。

这里有解释Configure core services with forRoot, but that section doesn't explain about the lazy-loading issue. That is explained with a little warning at the end of Shared Modules

Do not specify app-wide singleton providers in a shared module. A lazy loaded module that imports that shared module will make its own copy of the service.

@NgModule({})
class SharedModule {
  static forRoot() {
    return {
      ngModule: SharedModule,
      providers: [ MyService ]
    };
  }
}

@NgModule({
  import: [ SharedModule.forRoot() ]
})
class AppModule {}

@NgModule({
  imports: [ SharedModule ]
})
class LazyLoadedModule {}

这可以确保延迟加载的模块不会获得服务。但是无论模块是否延迟加载,这都是推荐用于 app-wide 服务的模式。不过需要注意的是,如果您没有任何惰性加载模块,不使用 forRoot 模式,而只是导入 SharedModule,那么它只会是该服务的一个实例。但是这个模式还是应该被推荐遵循的。


更新

我想我没有完全看问题就匆忙回答了。在问题中,没有提到任何共享模块。看来 OP 只是试图将服务添加到应用程序模块和延迟加载的 child 模块中的 @NgModule.providers

在这种情况下,只需从 child 模块 providers 中删除该服务即可。不需要。 app模块中添加的就够child使用了

请记住 providers 是应用程序范围的(除了在问题情况下 post 是关于),而 declarations 不是。

这应该可行,但我仍然建议您使用 SharedModule 概念,其中包含 common services,pipes ,指令和组件.

Shared/SharedModule

import { NgModule,ModuleWithProviders } from '@angular/core';
import { CommonModule }        from '@angular/common';

import { MyService } from './my.service';

@NgModule({
  imports:      [ CommonModule ],
  declarations: [],
  exports:      [ CommonModule ]
})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [ MyService ]                       //<<<====here
    };
  }
}

AppModule

import {SharedModule} from './shared/shared.module';
...
@NgModule({
   imports:[ BrowserModule,SharedModule.forRoot()],  //<<<====here
   providers: []
});

我有一个带有服务的单独布局模块,该服务需要在其他功能模块上工作,使用延迟加载

我能够通过直接从布局模块导出服务来解决问题

@NgModule({
    declarations: [...],
    imports: [...],
    exports: [...],
})
export class LayoutModule {
    ...
}

export { LayoutService }