1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Nest.jsのProviderとは

Posted at

はじめに

AdventCalendar2024 最終日。1人で走り切ったらもらえるQiitaのTシャツがほしくて毎日頑張って記事を書いてきました。

初めてこういうイベントに参加して記事を書きましたが、こういうのは事前の準備がないと内容が薄いなと感じたので、次参加するときはもっと良い内容を書けるようにしたいなと思った次第です。(今回は12/1に勢いで参加したので…)

余談はさておき、本編に入っていきます。
今回はNest.jsのProviderについて勉強したのでまとめていきます。

Providerとは

サービス・リポジトリ・ファクトリ・ヘルパー等のインスタンスを提供するための基本的な構成要素。

使いたいModuleで定義する必要がある。

Service
import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';

@Injectable()
export class CatsService {
  private readonly cats: Cat[] = [];

  create(cat: Cat) {
    this.cats.push(cat);
  }

  findAll(): Cat[] {
    return this.cats;
  }
}
Module
import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
import { CatsService } from './cats/cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
})
export class AppModule {}

依存性注入

依存性注入(Dependency Injection、DI) とは、オブジェクトがその依存関係を自分で作成するのではなく、外部から提供される設計パターンである。

DIを使わない場合、自分でインスタンス作成をする必要があるが、使う場合は以下のように宣言することで外部から簡単にインスタンスを取得できる。

DIを使いたい場合は@Injectable()を使ってそのProviderを定義する必要がある、

// DIを使わない場合
class CatsController {
  private catsService: CatsService;

  constructor() {
    this.catsService = new CatsService(); // 自分でインスタンスを作成
  }
}


// DIを使う場合
@Injectable()
class CatsService {
  // CatsServiceのロジック
}

@Controller('cats')
class CatsController {
  constructor(private readonly catsService: CatsService) {} // 外部から注入

  // CatsControllerのロジック
}

スコープ

Providerはスコープと呼ばれるライフタイムがある。

スコープには以下の3種類がある。

  1. DEFAULT:アプリケーション全体(起動から終了まで)で一度だけインスタンス化され、全てのリクエストで同じインスタンスが共有される
  2. REQUEST:各リクエストごとに新しいインスタンスが作成される。同じリクエスト内ではインスタンスは共有される
  3. TRANSIENT:依存関係が要求されるたびに新しいインスタンスが作成される。同じリクエスト内だったとしてもリクエスト内で複数回依存関係が要求された場合はその回数だけ作成される

オプションプロバイダー

依存関係が必ずしも存在しなくても良い場合(例えばアプリケーションに必須の動作ではない)に使用する。

@Optional()を使って定義する。

import { Injectable, Optional, Inject } from '@nestjs/common';

@Injectable()
export class HttpService<T> {
  constructor(@Optional() @Inject('HTTP_OPTIONS') private httpClient: T) {}
}

プロパティベースのインジェクション

これまでのものはコンストラクタを介してプロバイダーが注入されていたが、プロパティに直接依存関係を注入する方法。

@Injectを使って定義する。

@Injectable()
class CatsService {
  // CatsServiceのロジック
}

@Injectable()
class DogsService {
  // DogsServiceのロジック
}

@Injectable()
class AnimalService {
  @Inject(CatsService)
  private readonly catsService: CatsService;

  @Inject(DogsService)
  private readonly dogsService: DogsService;

  someMethod() {
    this.catsService.someMethod();
    this.dogsService.someMethod();
  }
}

ただし、クラスが他のクラスを継承していない場合はコンストラクタによる依存性注入を行った方が良い(@Inject()constructor() + @Injectable()はほぼ同じ)。

理由としては以下が挙げられる。

  • 明示的な依存関係の宣言
  • 可読性の向上
  • テストの容易さ

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?