2

問題:

angularでルーティングされていないモジュールの遅延読み込みを設定しています。私が使用したバージョン7では、モジュールを遅延ロードし、モジュールへの最初のエントリポイントを取得するNgModuleFactoryLoader機能です(アウトケースのサービス)load

this.loader.load('path-to-module')
  .then(factory => {
    const module = factory.create(this._injector);
    return module.injector.get(EntryService);
  });

しかし、Angular 8NgModuleFactoryLoaderでは非推奨になっているため、代わりにその方法でモジュールをロードする必要があります。

import('path-to-module')
  .then(m => m.MyModule)
  .then(myModule => {
    ...
});

ここでの問題は、新しい遅延読み込み (IVY のアイデアの 1 つ - ファクトリがない) で、ファクトリを取得してプロバイダを取得できないことです。

私がすでに試したこと:

最初の解決策(製品にAOTコンパイラを使用しているため、私たちには適していないJITコンパイラでのみ機能します)

import('path-to-module')
  .then(m => m.MyModule)
  .then(myModule => {
    return this._compiler.compileModuleAsync(myModule)
      .then(factory => {
        const module = factory.create(this._injector);
        return module.injector.get(EntryService);
      });
});

2番目の解決策(ダーティで完全にチェックされngInjectorDefていません。IVYの新機能を使用しており、まだ説明されているAPIはありません):

import('path-to-module')
  .then(m => m.MyModule)
  .then(myModule => {
    const providers = myModule['ngInjectorDef'].providers; // Array<Providers>
    ... find EntryService in providers
});

ngInjectorDef- angular によって追加され、ファクトリ、プロバイダー、およびインポートのプロパティを持つ静的モジュール クラス プロパティです。

ソース:

4

1 に答える 1

4

ngInjectorDefプロパティへのアクセスが「汚いハック」であるとは言いません。はい、Igor Minar が言ったように、Ivy は Angular 8 のオプトイン プレビューであるため、どこにも文書化されていませんdirectiveInject

providersプロパティでサービスを検索しないでください。20 以上のプロバイダーがあり、プロダクションでは名前が や のように縮小されると想像してEntryServiceください。tk

Ivy を使用する場合 - というプライベート関数があり、createInjectorモジュール コンストラクターを引数として受け取ります。

@Injectable()
export class EntryService {
  public logFromEntryService(): void {
    console.log('Logging from EntryService...');
  }
}

@NgModule({
  providers: [EntryService]
})
export class EntryModule {
  public static getEntryService: () => EntryService = null;

  constructor(injector: Injector) {
    EntryModule.getEntryService = () => injector.get(EntryService);
  }
}

このようなコードがあると仮定して、動的インポートを使用してこれをロードしましょうEntryModule:

import { ɵcreateInjector as createInjector } from '@angular/core';

export class AppComponent {
  constructor(private injector: Injector) {
    this.loadEntryModule();
  }

  private async loadEntryModule(): Promise<void> {
    const { EntryModule } = await import('./entry.module');
    createInjector(EntryModule, this.injector);
    EntryModule.getEntryService().logFromEntryService();
  }
}

createInjectorインスタンス化の後、インスタンス化に使用されEntryModuleます -getEntryService静的メソッドは等しくありませんnull

injector次のように、プロパティを公開することもできます。

public static injector: Injector = null;

constructor(injector: Injector) {
  EntryModule.injector = injector;
}

これは、一種のアンチパターンであるサービス ロケーターとして扱われる可能性があります。しかし、あなた次第です!

于 2019-07-23T21:04:07.657 に答える