Есть ли Singleton в NestJS?

«Есть ли Singleton в NestJS?» — вопрос из категории NestJS, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, в NestJS паттерн Singleton является основным и встроенным механизмом управления зависимостями (Dependency Injection). По умолчанию все провайдеры (помеченные декоратором @Injectable()), такие как сервисы, репозитории или кастомные провайдеры, регистрируются как синглтоны. Это означает, что на все время жизненного цикла приложения создается и повторно используется один единственный экземпляр класса.

Пример синглтона-сервиса:

// logger.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class LoggerService {
  private logCount = 0;

  log(message: string) {
    this.logCount++;
    console.log(`[#${this.logCount}] ${new Date().toISOString()}: ${message}`);
  }
}

При инжекции этого сервиса в несколько контроллеров или других сервисов, они получат один и тот же экземпляр LoggerService, что видно по общему счетчику logCount.

// app.controller.ts
@Controller()
export class AppController {
  constructor(private readonly logger: LoggerService) {}

  @Get()
  getHello() {
    this.logger.log('Request to /'); // Счетчик увеличится для всех инстансов
    return 'Hello';
  }
}

Это поведение можно изменить, задав другой scope (область видимости):

  • Scope.REQUEST: новый экземпляр создается для каждого входящего HTTP-запроса.
  • Scope.TRANSIENT: новый экземпляр создается для каждого потребителя (контроллера/сервиса), куда он инжектируется.
import { Injectable, Scope } from '@nestjs/common';

@Injectable({ scope: Scope.REQUEST })
export class RequestScopedService {}