Що таке хуки життєвого циклу в NestJS?
Хуки життєвого циклу в NestJS
NestJS надає хуки життєвого циклу, які дозволяють виконувати код у певні моменти під час запуску та завершення роботи програми. Вони є необхідними для ініціалізації з'єднань, запуску фонових завдань та коректного завершення роботи.
Доступні хуки
| Інтерфейс хука | Метод | Коли викликається |
|---|---|---|
OnModuleInit | onModuleInit() | Після ініціалізації провайдерів модуля |
OnApplicationBootstrap | onApplicationBootstrap() | Після ініціалізації всіх модулів, перед прослуховуванням |
OnModuleDestroy | onModuleDestroy() | Після виклику app.close() |
BeforeApplicationShutdown | beforeApplicationShutdown(signal) | Перед завершенням роботи (отримує сигнал ОС) |
OnApplicationShutdown | onApplicationShutdown(signal) | Після закриття всіх з'єднань |
OnModuleInit — Налаштування після DI
typescript
import { Injectable, OnModuleInit } from '@nestjs/common';
@Injectable()
export class DatabaseService implements OnModuleInit {
async onModuleInit() {
// Викликається один раз після створення всіх провайдерів у модулі
await this.connect();
console.log('База даних підключена');
}
private async connect() {
// Встановлення з'єднання з базою даних
}
}OnApplicationBootstrap — Після повної ініціалізації
typescript
import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
@Injectable()
export class SeedService implements OnApplicationBootstrap {
constructor(
private readonly usersService: UsersService,
private readonly configService: ConfigService,
) {}
async onApplicationBootstrap() {
if (this.configService.get('NODE_ENV') === 'development') {
await this.seedDatabase();
}
}
private async seedDatabase() {
const count = await this.usersService.count();
if (count === 0) {
await this.usersService.create({ name: 'Admin', email: 'admin@app.com' });
console.log('База даних заповнена');
}
}
}Коректне завершення роботи
typescript
// main.ts — увімкнення хуків завершення роботи
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableShutdownHooks(); // слухати SIGTERM, SIGINT
await app.listen(3000);
}typescript
// services/queue.service.ts
import { Injectable, OnApplicationShutdown, BeforeApplicationShutdown } from '@nestjs/common';
@Injectable()
export class QueueService implements BeforeApplicationShutdown, OnApplicationShutdown {
private isShuttingDown = false;
beforeApplicationShutdown(signal: string) {
console.log(`Отримано сигнал: ${signal}`);
this.isShuttingDown = true;
// зупинити прийом нових завдань
}
async onApplicationShutdown(signal: string) {
await this.waitForActiveJobs();
await this.closeConnection();
console.log('Служба черги завершила роботу коректно');
}
private waitForActiveJobs(): Promise<void> {
return new Promise(resolve => setTimeout(resolve, 2000));
}
}OnModuleDestroy — Очищення для кожного модуля
typescript
@Injectable()
export class CacheService implements OnModuleDestroy {
private client: RedisClient;
async onModuleDestroy() {
await this.client.quit();
console.log('З'єднання з Redis закрито');
}
}Повний порядок життєвого циклу
1. Модулі ініціалізовані (створені провайдери)
2. onModuleInit() — для кожного провайдера
3. onApplicationBootstrap() — для кожного провайдера
4. app.listen() — сервер починає приймати запити
---
[SIGTERM / app.close()]
5. beforeApplicationShutdown(signal) — для кожного провайдера
6. Сервер перестає приймати нові з'єднання
7. onModuleDestroy() — для кожного провайдера
8. onApplicationShutdown(signal) — для кожного провайдера
9. Процес завершуєтьсяРезюме
Хуки життєвого циклу роблять сервіси NestJS обізнаними про життєвий цикл програми. Використовуйте OnModuleInit для налаштування після DI (з'єднання з БД, прогрів кешу), OnApplicationBootstrap для завдань після запуску (заповнення, перевірка працездатності), а також OnApplicationShutdown + app.enableShutdownHooks() для коректного завершення роботи (дренування з'єднань, завершення завдань).
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.