詳細ガイド
依存性の注入

注入可能なサービスの作成

サービスとは、アプリケーションが必要とする値、関数、または機能を包括的に表すカテゴリーです。 サービスは、通常、狭く明確に定義された目的を持つクラスです。 コンポーネントは、DIを使用できるクラスの一種です。

Angularは、モジュール性と再利用性を高めるために、コンポーネントとサービスを区別しています。 コンポーネントのビュー関連の機能を他の処理から分離することで、コンポーネントクラスをスリムで効率的にできます。

理想的には、コンポーネントの役割は、ユーザー体験を実現することだけです。 コンポーネントは、データバインディング用のプロパティとメソッドを提供し、ビュー(テンプレートによってレンダリングされる)とアプリケーションロジック(多くの場合、モデルの概念が含まれる)の仲介役を果たすべきです。

コンポーネントは、サーバーからのデータの取得、ユーザー入力の検証、またはコンソールへの直接ログ記録など、特定のタスクをサービスに委譲できます。 このような処理タスクを注入可能サービスクラスで定義することで、これらのタスクをどのコンポーネントからも利用できるようになります。 また、状況に応じて、同じ種類のサービスの異なるプロバイダーを構成することで、アプリケーションをより適応性高くできます。

Angularは、これらの原則を強制しません。 Angularは、アプリケーションロジックをサービスに分解し、それらのサービスをDIを介してコンポーネントに提供することを容易にすることで、これらの原則に従うように支援します。

サービスの例

ブラウザコンソールにログ記録するサービスクラスの例を以下に示します。

src/app/logger.service.ts (class)

      
export class Logger {  log(msg: unknown) { console.log(msg); }  error(msg: unknown) { console.error(msg); }  warn(msg: unknown) { console.warn(msg); }}

サービスは、他のサービスに依存できます。 たとえば、次のHeroServiceLoggerサービスに依存し、BackendServiceを使用してヒーローを取得します。 そのサービスは、さらにHttpClientサービスに依存して、サーバーからヒーローを非同期に取得する場合があります。

src/app/hero.service.ts (class)

      
export class HeroService {  private heroes: Hero[] = [];  constructor(    private backend: BackendService,    private logger: Logger) {}  async getHeroes() {    // Fetch    this.heroes = await this.backend.getAll(Hero);    // Log    this.logger.log(`Fetched ${this.heroes.length} heroes.`);    return this.heroes;  }}

注入可能なサービスの作成

Angular CLIは、新しいサービスを作成するためのコマンドを提供します。 次の例では、既存のアプリケーションに新しいサービスを追加します。

src/app/heroesフォルダーに新しいHeroServiceクラスを生成するには、次の手順に従います。

  1. 次のAngular CLIコマンドを実行します。
      
ng generate service heroes/hero

このコマンドは、次のデフォルトのHeroServiceを作成します。

src/app/heroes/hero.service.ts (CLI-generated)

      
import { Injectable } from '@angular/core';@Injectable({  providedIn: 'root',})export class HeroService {}

@Injectable()デコレーターは、AngularがDIシステムでこのクラスを使用できることを指定します。 メタデータprovidedIn: 'root'は、HeroServiceがアプリケーション全体で提供されることを意味します。

ヒーローのモックデータを取得するために、mock.heroes.tsからヒーローを返すgetHeroes()メソッドを追加します。

src/app/heroes/hero.service.ts

      
import { Injectable } from '@angular/core';import { HEROES } from './mock-heroes';@Injectable({  // このサービスがルートアプリケーションインジェクターによって作成されることを宣言します。  providedIn: 'root',})export class HeroService {  getHeroes() {    return HEROES;  }}

明確さと保守性の観点から、コンポーネントとサービスは別々のファイルに定義することをお勧めします。

サービスの注入

コンポーネントにサービスを依存性として注入するには、コンポーネントのconstructor()を使用し、依存性の型を持つコンストラクター引数を指定します。

次の例では、HeroListComponentコンストラクターにHeroServiceを指定しています。 heroServiceの型はHeroServiceです。 HeroServiceクラスはすでに@Injectableデコレーターで修飾されているため、AngularはHeroService型を依存性として認識します。

src/app/heroes/hero-list.component (constructor signature)

      
constructor(heroService: HeroService)

他のサービスでのサービスの注入

サービスが別のサービスに依存する場合、コンポーネントへの注入と同じパターンに従います。 次の例では、HeroServiceLoggerサービスに依存して、そのアクティビティを報告します。

src/app/heroes/hero.service.ts

      
import { Injectable } from '@angular/core';import { HEROES } from './mock-heroes';import { Logger } from '../logger.service';@Injectable({  providedIn: 'root',})export class HeroService {  constructor(private logger: Logger) {}  getHeroes() {    this.logger.log('Getting heroes.');    return HEROES;  }}

この例では、getHeroes()メソッドは、ヒーローを取得する際にメッセージをログ記録することで、Loggerサービスを使用しています。

次のステップ