J'ai suivi ce tutoriel, pour comprendre le chargement paresseux, et ci-dessous mon inférence.
Scénario 1: Les services sont fournis en les plaçant dans le tableau providers
d'un module enfant
Scénario 2: Les services sont fournis dans un module enfant en utilisant l'approche forRoot
Avec le scénario 1 en contexte,
Avec le scénario 2 en contexte,
Si un module enfant est chargé avec impatience, une instance du service est ajoutée à l'injecteur racine.
Si un module enfant est chargé paresseusement, la même instance du service est disponible à la fois dans le module racine et dans le module enfant, ce qui est le cas d'utilisation habituel.
Ils ont mentionné ce qui suit.
Au début,
Donc, même lorsque vous utilisez des modules, il n'y a aucun moyen d'avoir un service "privé" à moins que ... le module ne soit chargé paresseusement.
Finalement,
Bien que cette syntaxe soit un peu plus compliquée que l'original, elle nous garantira qu'une seule instance de CreditCardService est ajoutée au module racine. Lorsque le CreditCardModule est chargé (même paresseux), aucune nouvelle instance de ce service ne sera ajoutée à l'injecteur enfant.
Si l'instance va également être disponible dans l'injecteur racine, comment disent-ils que le service est "privatisé"?
Je suis confus. Quelqu'un veuillez clarifier.
Ce fil est assez ancien mais je vais répondre à ce que j'ai appris en recherchant sur ce sujet les futurs trébucheurs sur ce fil.
Le concept de privatisation d'un service avec chargement paresseux est approprié et pour les raisons suivantes:
Angular Doc dit que l'une des façons d'étendre votre service est de les fournir à son propre module (supposons Module-A). Et seulement lorsqu'un autre module B importe le module A, il aura le fournisseur de ce service (du module A) et pourra donc y accéder. Cela fonctionne en fait pour les modules paresseux et non pour les modules désireux pour les raisons ci-dessous:
Lorsque vous implémentez la méthode d'étendue ci-dessus pour les modules désireux, cela créera un fournisseur pour les services de ce module (supposons que le module A). Mais lorsque ce module particulier 'A' est importé dans le module racine (comme tous les modules désireux devraient l'être), l'injecteur racine créera une seule instance de ce service et rejettera toute instance en double de ce service dans la portée de l'injecteur racine (si module A a été importé dans tout autre module désireux). Ainsi, tous les modules désireux ont accès à un service singleton de n'importe quel module importé dans le module racine.
Si vous souhaitez toujours avoir accès au service paresseux à partir de l'injecteur racine. Vous pouvez utiliser:
@Injectable({
providedIn: 'root'
})
décorateur dans le service paresseux et l'injecter dans l'injecteur racine sans charger le module paresseux à la charge de l'application.
L'exemple que vous suiviez n'est pas une véritable implémentation du chargement paresseux si vous avez accès aux services paresseux dans votre module racine, sans le providedIn: root
objet. Vous pouvez passer par ce lien: https://angular.io/guide/providers#limiting-provider-scope-by-lazy-loading-modules
providedIn: 'root'
est le moyen le plus simple et le plus efficace de fournir des services depuis Angular 6:
Pour plus d'informations, lisez les documentation et FAQ NgModule
Btw:
Voici comment je le fais: https://stackblitz.com/edit/angular-lazy-service-module?file=src%2Fapp%2Fapp.component.ts
Ceci est une preuve de concept. Vous devez faire attention à l'injecteur que vous utilisez (au cas où le service paresseux aurait besoin de certaines dépendances) et à la façon dont vous gérez le cycle de vie du service chargé paresseux (combien d'instances vous créez, etc.).
Mon cas d'utilisation est qu'il existe un assez gros service (exportation vers Excel, plus de 400 Ko gziped) qui est utilisé dans plusieurs domaines de l'application, mais je ne veux pas le charger/analyser jusqu'à ce qu'il soit réellement nécessaire - chargement initial plus rapide! (J'ai en fait également utilisé une stratégie de précharge de retard qui charge les modules après quelques secondes).
L'idée de base est que vous le définissez comme un module paresseux dans une route (que vous n'utilisez pas réellement) mais que vous déclenchez le chargement manuellement. Vous résolvez également le service à partir de ce module (une fois que vous l'avez) en utilisant un jeton d'injection.
module paresseux
import { NgModule } from '@angular/core';
import { LazyService } from './lazy-service.service';
import { LAZY_SERVICE_TOKEN } from './lazy-service.contract';
@NgModule({
providers: [{ provide: LAZY_SERVICE_TOKEN, useClass: LazyService }],
})
export class LazyServiceModule {
}
service paresseux
import { Injectable } from '@angular/core';
import { LazyService as LazyServiceInterface } from './lazy-service.contract';
@Injectable()
export class LazyService implements LazyServiceInterface {
process(msg: string) {
return `This message is from the lazy service: ${msg}`;
}
}
module d'application
@NgModule({
imports: [BrowserModule,
RouterModule.forRoot([
// whatever other routes you have
{
path: '?$lazy-service', //some name that will not be used
loadChildren: 'app/lazy-service/lazy-service.module#LazyServiceModule',
},
])],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
l'utiliser à l'intérieur d'un composant
constructor(
private loader: NgModuleFactoryLoader,
private injector: Injector,
) {
}
async loadServiceAndCall() {
const factory = await this.loader.load('app/lazy-service/lazy-service.module#LazyServiceModule');
const moduleRef = factory.create(this.injector);
const service: LazyService = moduleRef.injector.get(LAZY_SERVICE_TOKEN);
this.value = service.process('"from app.component.ts"')
}
La meilleure explication que je pourrais vous donner est dans cet article .
Bref, en bref:
Pour les services de chargement paresseux, vous pouvez vérifier le lien ci-dessous