¿Pueden los módulos lazy-loaded compartir la misma instancia de un servicio proporcionado por su padre?


Acabo de encontrarme con un problema con un módulo lazy-loaded donde los módulos padre e hijo requieren el mismo servicio pero crean una instancia cada uno. La declaración es idéntica para ambos, es decir

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

Y aquí está la configuración de enrutamiento

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

Que, por supuesto, se importa en el módulo padre como

RouterModule.forChild(parentRoutes)

¿Cómo puedo hacer esto si quiero compartir la misma instancia de servicio?

Author: Thorsten Westheider, 2016-09-24

2 answers

Usando un forRoot, como se mencionó aquí, es lo que probablemente necesites. El problema que está destinado a resolver, está directamente relacionado con el problema que está experimentando con los módulos lazy loaded que obtienen su propio servicio.

Se explica aquí en Configure los servicios principales con forRoot, pero esa sección no explica el problema de la carga perezosa. Esto se explica con una pequeña advertencia al final de Módulos compartidos

No especifique app-wide singleton providers en un módulo compartido. Un módulo lazy loaded que importa ese módulo compartido hará su propia copia del servicio.

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

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

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

Esto asegura que el módulo lazy loaded no reciba el servicio. Pero ya sea que el módulo esté cargado perezosamente o no, este es el patrón que se recomienda para los servicios de toda la aplicación. Aunque debe tenerse en cuenta que si no tiene ningún módulo lazy loaded, no usa el patrón forRoot, y solo importa SharedModule, solo será uno instancia del servicio. Pero este patrón aún debe recomendarse que se siga.


ACTUALIZACIÓN

Supongo que salté a responder rápidamente sin mirar completamente la pregunta. En la pregunta, no hay ninguna mención de ningún módulo compartido. Parece que el OP simplemente está tratando de agregar el servicio al @NgModule.providers tanto en el módulo app como en el módulo hijo lazy loaded.

En este caso, simplemente elimine el servicio del módulo secundario providers. No es necesario. El uno añadido en el módulo app es suficiente para que el niño sea utilizado.

Solo recuerda que providers son app wide (excepto en el caso del problema que trata este post), mientras que declarations no lo son.

 46
Author: Paul Samsotha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-14 06:20:33

Esto debería funcionar, pero aún así te sugiero que vayas con SharedModule concepto que contiene común servicios,tuberías, directivas y componentes.

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: []
});
 16
Author: micronyks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-24 05:46:31