Actualmente tengo un problema con los módulos y servicios con carga diferida que se providedIn en este módulo con carga diferida.
Tengo una estructura de carpetas que se ve así:
aplicación
-> featureModule1 (carga perezosa)
-> featureModule2 (carga perezosa)
-->servicios
--->servicio1.ts
Quiero que este service1.ts solo esté disponible en featureModule2. Así que incluí @Injectable
// service.ts @Injectable({ providedIn: featureModule2 }) export class service1 { /* some logic */ }Cuando trato de enrutar a este módulo con carga diferida, aparece un error de consola:
// console ERROR Error: Uncaught (in promise): ReferenceError: Cannot access 'featureModule2' before initialization ReferenceError: Cannot access 'featureModule2' before initializationMi ruta de carga diferida actual se ve así:
// app-routing.module.ts const routes: Routes = [ {path: '', redirectTo: '', pathMatch: 'full'}, { path: 'feature1', loadChildren: () => import('./feature1/feature1.module').then(m => m.featureModule1) }, { path: 'feature2', loadChildren: () => import('./feature2/feature2.module').then(m => m.featureModule2) } ];Intenté proporcionarlo en el módulo:
// featureModule1 @NgModule({ declarations: [ featureComponent ], imports: [ ... ], providers: [ service1 ] })Eso no funciona.
Y traté de importar service1.ts directamente como un componente ( featureComponent ).
// featureComponent import { service1 } from '../featureModule2/services/service1.service'; @Component({ ... }) export class featureComponent { constructor(private service1: service1) { } ngOnInit(): void { this.service1.init(); } }Este enfoque conduce al mismo mensaje de error.
La única forma de solucionar este problema en este momento es crear un módulo "envoltorio" que importe todos los demás módulos con servicios @Injectable .
¿Hay una manera diferente para este problema? Los servicios en cada módulo no deben inyectarse en root ni en any porque solo deben estar disponibles en cada módulo de características.
Solo tienes que declararlo en la sección de providers y funcionará. He usado la variante del proveedor useFactory para mostrar claramente que se usa para realizar la inyección y angular no es simplemente new LazyService en su lugar. Trabajaré con providers:[LazyService] también (que es un 'proveedor de clase', creo, igual a useClass:LazyService )
En módulo perezoso
import { CustomerListComponent, LazyService } from './customer-list/customer-list.component'; @NgModule({ imports: [CommonModule, CustomersRoutingModule], declarations: [CustomerListComponent], providers: [ { provide: LazyService, useFactory: () => new LazyService('proofThatItIsFromPRoviders') } ] }) export class CustomersModule {}en el componente perezoso del mismo módulo ("el servicio printsLazy funciona como prueba de que es de PRoviders")
export class LazyService { constructor(private test: string) {} public say() { console.log('Lazy service works', this.test); } } @Component({ selector: 'app-customer-list', templateUrl: './customer-list.component.html', styleUrls: ['./customer-list.component.css'] }) export class CustomerListComponent implements OnInit { constructor(private lazy: LazyService) {} ngOnInit() { this.lazy.say(); } }falla la inyeccion en otro modulo
@Component({ selector: 'app-order-list', templateUrl: './order-list.component.html', styleUrls: ['./order-list.component.css'] }) export class OrderListComponent implements OnInit { constructor(private lazy:LazyService) { } ngOnInit() { this.lazy.say(); } }Ejemplo de trabajo aquí https://stackblitz.com/edit/angular-s5xxnb-j9ch1z?file=src%2Fapp%2Forders%2Forder-list%2Forder-list.component.ts
Cuando configuramos un servicio como este:
@Injectable({ providedIn: featureModule2 }) export class TestService { } Significa que TestService no estará disponible para las aplicaciones a menos que importen featureModule2.
Dado que featureModule2 es un módulo de carga diferida, definitivamente no desea especificar esto en las importaciones de módulos de la aplicación y, por lo tanto, deberá usar
@Injectable({ providedIn: 'any' }) export class TestService { }o
@Injectable({ providedIn: 'root' }) export class TestService { } La diferencia entre los dos anteriores es que cuando usamos ' root habrá una sola instancia de ese servicio a través de la aplicación. En el caso de ' any ' para el módulo con carga diferida habrá una nueva instancia de ese servicio y para el módulo con carga ansiosa actuará como un singleton.