Angular 4依存注入チュートリアルの4 FactoryProviderの使用


目次
  • Angular 4依存注入チュートリアルの1つ依存注入概要
  • Angular 4依存注入チュートリアルの2コンポーネントサービス注入
  • Angular 4依存注入チュートリアルの3 ClassProviderの使用
  • Angular 4依存注入チュートリアルの4 FactoryProviderの使用
  • Angular 4依存注入チュートリアルの5 FactoryProvider構成依存オブジェクト
  • Angular 4依存注入チュートリアルの6 Injectableアクセサリ
  • Angular 4依存注入チュートリアルの7 ValueProviderの使用
  • Angular 4依存注入チュートリアルの8 InjectTokenの使用
  • 読書の心得
    このチュートリアルの開発環境と開発言語:
  • Angular 4 +
  • Angular CLI
  • TypeScript

  • 基礎知識
    FactoryProviderの役割
    FactoryProviderは、プロジェクト(インジェクタ)に、useFactoryに対応する関数を呼び出すことによって、Tokenに対応する依存オブジェクトを返すために使用される.
    FactoryProviderの使用
    function serviceFactory() { 
        return new Service();
    }
    
    const provider: FactoryProvider = {
      provide: 'someToken', useFactory: serviceFactory, deps: []
    };

    FactoryProviderインタフェース
    export interface FactoryProvider {
      //             Token ,Token    Type、InjectionToken、
      // OpaqueToken       
      provide: any;
      //              
      useFactory: Function;
      //       
      deps?: any[];
      //       multiple providers,  multiple  ,    Token     
      //     
      multi?: boolean;
    }

    FactoryProvider
    基礎知識を紹介してから、すぐに本題に入ります.前に作成したHeroComponentコンポーネントを覚えていますか?
    import { Component, OnInit } from '@angular/core';
    import { HeroService } from '../hero.service';
    
    @Component({
      selector: 'app-hero',
      template: `
        
    • ID: {{hero.id}} - Name: {{hero.name}}
    ` }) export class HeroComponent implements OnInit { constructor(private heroService: HeroService) { } heros: Array; ngOnInit() { this.heros = this.heroService.getHeros(); } }

    では、ヒーローデータを取得するときにデバッグ情報を出力したいとしたら、どうすればいいのでしょうか.What~、この問題は簡単ではないでしょうか.console.log APIを直接使って対応する情報を出力すればいいのではないでしょうか.
    console.log('Fetching heros...');
    this.heros = this.heroService.getHeros();

    また、複数のコンポーネントがHeroServiceを使用してヒーローデータを取得する場合、各コンポーネントに対応する文を追加する必要がありますか.また、出力されたデバッグ情報を変更するには、プログラム内の複数の場所を変更する必要があります.実は私たちは一般的に開発段階でデバッグ情報を出力するだけで、上の案は合理的ではなく、柔軟ではありません.
    実際には、HeroServiceサービスを導入した前の考え方を参考にして、上記の問題を解決するためにLoggerServiceを作成することができます.
    LoggerServiceサービスの作成
    export class LoggerService {
        constructor(private enable: boolean) { }
    
        log(message: string) {
            if(this.enable) {
               console.log(`LoggerService: ${message}`);
            }
        }
    }

    ロガーサービスの構成
    @NgModule({
      ...
      providers: [
         HeroService,
         LoggerService
      ],
      bootstrap: [AppComponent]
    })
    export class AppModule { }

    ロガーサービスの使用
    import { Component, OnInit } from '@angular/core';
    import { HeroService } from '../hero.service';
    import { LoggerService } from './../logger.service';
    
    @Component({
      selector: 'app-hero',
      template: `
        
    • ID: {{hero.id}} - Name: {{hero.name}}
    ` }) export class HeroComponent implements OnInit { heros: Array; constructor(private heroService: HeroService, private loggerService: LoggerService) { } ngOnInit() { this.loggerService.log('Fetching heros...'); this.heros = this.heroService.getHeros(); } }

    上記のコードが実行されると、次の異常情報が放出されます.
    Uncaught Error: Can't resolve all parameters for LoggerService: (?).

    ある読者は、目が明るくなると、LoggerServiceサービスを作成するときに、@Injectable装飾器を使うのを忘れたのかもしれません.ははは、実は私はわざとですが、@Injectable()を加えた後、以下の異常を投げました.
    ERROR Error: No provider for Boolean!

    なぜ上の異常情報が出てくるのでしょうか?前に作成したLoggerServiceサービスを見てみましょう.
    export class LoggerService {
        constructor(private enable: boolean) { }
        // ...
    }

    Angularでは注入を構成することによって依存オブジェクトを注入し,private enable: booleanType型のオブジェクトを注入することを示す.次に、booleanは、基本データ型を表し、必要なType型ではない.
    export function isType(v: any): v is Type {
      return typeof v === 'function';
    }

    次に、最初に投げ出された異常を見てみましょう.
    Uncaught Error: Can't resolve all parameters for LoggerService: (?).

    実際には、問題の承諾もLoggerServiceクラスの構造関数で、LoggerServiceオブジェクトを作成するときに、enableパラメータの値を設定する必要があります.では、どのように解決すればいいのでしょうか.もちろん、私たちの主役-FactoryProviderを使用することができます.具体的には以下の通りです.
    FactoryProviderの使用
    @NgModule({
       ...,
       providers: [
         HeroService,
         {
          provide: LoggerService, 
          useFactory: () => {
            return new LoggerService(true);
          }
        }
       ],
      bootstrap: [AppComponent]
    })
    export class AppModule { }

    コードを更新した後、華麗な保存操作を行い、最後にコンソールを開くと、予想される出力情報が表示されます.
    LoggerService: Fetching heros...

    これで終わり、FactoryProviderの関連内容については一段落し、次はFactoryProviderを使用して依存オブジェクトを構成する方法について説明します.