Що таке Singleton-провайдери?
Що таке Singleton-провайдер
Singleton-провайдер - це провайдер, у якого існує лише один екземпляр (instance) на весь застосунок NestJS. Коли контейнер NestJS вперше створює цей провайдер, він кешує екземпляр, і всі наступні запити до цього провайдера отримують ту саму копію.
Приклад
javascript
import { Injectable } from '@nestjs/common';
@Injectable()
export class CounterService {
private counter = 0;
increment() {
this.counter++;
return this.counter;
}
}І два контролери використовують цей сервіс:
javascript
import { Controller, Get } from '@nestjs/common';
import { CounterService } from './counter.service';
@Controller('a')
export class AController {
constructor(private readonly counterService: CounterService) {}
@Get()
add() {
return this.counterService.increment();
}
}
@Controller('b')
export class BController {
constructor(private readonly counterService: CounterService) {}
@Get()
add() {
return this.counterService.increment();
}
}Що відбудеться:
- NestJS створить один спільний екземпляр
CounterService; - обидва контролери (
AControllerіBController) використовуватимуть той самий об'єкт; - значення лічильника буде спільним:
| Запит | Результат |
|---|---|
GET /a → 1 | створюється вперше |
GET /b → 2 | використовує той самий екземпляр |
Чому це зручно
- Економія ресурсів: об'єкт створюється лише один раз.
- Спільний state: зручно, якщо потрібно кешувати дані, тримати пул підключень тощо.
- Простота: не потрібно вручну керувати часом життя об'єкта.
Як NestJS вирішує, що провайдер - Singleton
За замовчуванням усі провайдери в NestJS мають scope: DEFAULT,
а DEFAULT = singleton.
javascript
@Injectable({ scope: Scope.DEFAULT }) // те саме, що просто @Injectable()
export class MyService {}Інші типи областей видимості (Scope)
| Scope | Опис |
|---|---|
| Singleton (DEFAULT) | Один екземпляр на весь застосунок (за замовчуванням) |
| Request | Новий екземпляр на кожен HTTP-запит |
| Transient | Новий екземпляр при кожному впровадженні (щоразу новий об'єкт) |
Приклад Request-Scoped провайдера:
javascript
import { Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class RequestService {
constructor() {
console.log('Новий екземпляр для запиту!');
}
}У цьому випадку при кожному HTTP-запиті Nest створюватиме новий об'єкт, а не використовуватиме спільний.
Коли Singleton-провайдер - це добре
Чудово підходить для:
- сервісів зі спільною логікою, не залежною від запиту;
- логування, конфігурації, роботи з БД (одне підключення);
- кешування, токенів, сервісів, які не зберігають унікальні дані запиту.
Коли Singleton-провайдер - погана ідея
Не використовуй Singleton, якщо:
- провайдер зберігає стан, залежний від конкретного запиту;
- він має бути ізольований між користувачами;
- він містить дані користувача, які не можна ділити між запитами.
У таких випадках обирають Scope.REQUEST чи Scope.TRANSIENT.
Підсумок
| Поняття | Опис |
|---|---|
| Singleton-провайдер | Один спільний екземпляр провайдера на весь застосунок |
| Створюється | Один раз при ініціалізації модуля |
| Використовується | У всіх місцях, де він впроваджений |
| За замовчуванням | Усі провайдери NestJS - singleton |
| Переваги | Швидше, економніше, зручно для кешів, констант, БД |
| Обмеження | Не підходить для залежностей, унікальних на кожен запит |
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.