私は遅延読み込みを理解するために this チュートリアルに従っていますが、以下は私の推測です。
シナリオ1:サービスは、子モジュールのproviders
配列に配置することで提供されます
シナリオ2:forRoot
アプローチを使用して、子モジュールでサービスが提供されます。
シナリオ1のコンテキストで、
コンテキスト2のシナリオでは、
子モジュールが熱心にロードされると、サービスのインスタンスがルートインジェクターに追加されます。
子モジュールが遅延ロードされると、サービスの同じインスタンスがルートと子モジュールの両方で利用可能になります。これは通常の使用例です。
彼らは次のことに言及しています。
最初は
そのため、モジュールを使用する場合でも、モジュールが遅延ロードされない限り、「プライベート」サービスを使用する方法はありません。
最後に、
この構文は元の構文より少し複雑ですが、CreditCardServiceの1つのインスタンスのみがルートモジュールに追加されることを保証します。 CreditCardModuleがロードされると(遅延ロードされる場合でも)、そのサービスの新しいインスタンスは子インジェクターに追加されません。
インスタンスがルートインジェクターでも使用可能になる場合、サービスが「特権化されている」とどのように言いますか?
よくわかりません。誰か明確にしてください。
このスレッドはかなり古いものですが、このスレッドの将来のつまずきについてこのトピックを検索しながら学んだことにお答えします。
遅延読み込みを使用してサービスを民営化するという概念は適切であり、以下の理由によります。
Angular Docによると、サービスのスコープを設定する方法の1つは、サービスを独自のモジュールに提供することです(Module-Aを想定)。そして、他のモジュールBがモジュールAをインポートする場合にのみ、そのサービスのプロバイダーが(モジュールAから)取得され、アクセスできるようになります。これは実際には遅延モジュールで機能し、以下の理由で熱心なモジュールでは機能しません。
熱心なモジュールに対して上記のスコープメソッドを実装すると、そのモジュールのサービスのプロバイダーが作成されます(モジュールAを想定)。しかし、その特定のモジュール「A」がルートモジュールにインポートされると(すべての熱心なモジュールがそうであるように)、ルートインジェクターはそのサービスの単一インスタンスを作成し、ルートインジェクターのスコープ内のそのサービスの重複インスタンスを破棄します(ifモジュールAは他の熱心なモジュールにインポートされました)。したがって、すべての熱心なモジュールは、ルートモジュールにインポートされた任意のモジュールのシングルトンサービスにアクセスできます。
ルートインジェクターからレイジーサービスにアクセスしたい場合。以下を使用できます。
@Injectable({
providedIn: 'root'
})
遅延サービスのデコレータを使用し、アプリケーションのロード時に遅延モジュールをロードせずにルートインジェクタに注入します。
providedIn: root
オブジェクトなしでルートモジュールのレイジーサービスにアクセスできる場合、以下の例はレイジーロードの実際の実装ではありません。次のリンクを使用できます: https://angular.io/guide/providers#limited-provider-scope-by-lazy-loading-modules
providedIn: 'root'
は、Angular 6:以来、サービスを提供する最も簡単で効率的な方法です。
詳細については、 ドキュメント および NgModule FAQs を読むことを検討してください。
ところで:
ここに私がそれを行う方法があります: https://stackblitz.com/edit/angular-lazy-service-module?file=src%2Fapp%2Fapp.component.ts
これは概念実証です。使用するインジェクター(レイジーサービスに依存関係が必要な場合)と、レイジーロードされたサービスのライフサイクルの管理方法(作成するインスタンスの数など)に注意する必要があります。
私のユースケースは、アプリケーションの複数の領域で使用される非常に大きなサービス(Excelへのエクスポート、400 KB以上のgzip圧縮)がありますが、実際に必要になるまでロード/解析したくない-初期ロードが速い! (実際には、数秒後にモジュールをロードする遅延プリロード戦略も使用しました)。
基本的な考え方は、ルートで遅延モジュール(実際には使用しない)として定義するが、手動でロードをトリガーすることです。また、インジェクショントークンを使用して、そのモジュールのサービスを(一度取得したら)解決します。
遅延モジュール
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 {
}
怠zyなサービス
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}`;
}
}
アプリモジュール
@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 { }
コンポーネント内で使用する
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"')
}
この記事 で説明できます。
とにかく、要するに:
遅延読み込みサービスの場合は、以下のリンクを確認できます
[ 遅延ロードモジュールでサービスを提供し、そのサービスを遅延ロードモジュールとそのコンポーネントだけにスコープするにはどうすればよいですか?