Как избежать утечек памяти в Angular-приложении?angular-48

Утечки памяти в Angular возникают, когда ресурсы (объекты, подписки и т.д.) не освобождаются после уничтожения компонента или сервиса. Вот основные методы предотвращения утечек:

1. Отписка от Observables

Самая частая причина утечек — незакрытые подписки на RxJS Observables.

// Плохо: подписка не отменяется
this.someService.data$.subscribe(data => {...});

// Хорошо: ручная отписка
private subscription: Subscription;

ngOnInit() {
  this.subscription = this.someService.data$.subscribe(data => {...});
}

ngOnDestroy() {
  this.subscription.unsubscribe();
}

// Лучше: использование takeUntil
private destroy$ = new Subject<void>();

ngOnInit() {
  this.someService.data$
    .pipe(takeUntil(this.destroy$))
    .subscribe(data => {...});
}

ngOnDestroy() {
  this.destroy$.next();
  this.destroy$.complete();
}

2. Очистка таймеров и интервалов

Все setTimeout/setInterval должны быть очищены:

private timerId: any;

ngOnInit() {
  this.timerId = setInterval(() => {...}, 1000);
}

ngOnDestroy() {
  clearInterval(this.timerId);
}

3. Удаление слушателей событий

Слушатели событий DOM должны быть удалены:

@HostListener('window:scroll', ['$event'])
onScroll(event: Event) {...}

// Или для ручного добавления:
private removeListener: () => void;

ngOnInit() {
  this.removeListener = this.renderer.listen('document', 'click', () => {...});
}

ngOnDestroy() {
  this.removeListener();
}

4. Осторожность с глобальными сервисами

Сервисы, предоставленные в root, живут всё время приложения. Для временных данных используйте:

  • Локальные провайдеры в компонентах
  • Очистку данных в ngOnDestroy

5. Работа с Subject

Все Subject должны быть завершены:

private dataSubject = new Subject<string>();

ngOnDestroy() {
  this.dataSubject.complete();
}

6. Использование async pipe

В шаблонах предпочтительно использовать async pipe, который автоматически управляет подпиской:

<div>{{ data$ | async }}</div>

7. Очистка ссылок

Удаляйте ссылки на большие объекты:

private largeData: any;

ngOnDestroy() {
  this.largeData = null;
}

8. Использование OnPush change detection

Стратегия OnPush уменьшает количество проверок изменений и связанных с ними утечек.

Инструменты для обнаружения утечек:

  1. Chrome DevTools Memory Profiler
  2. Angular DevTools
  3. RxJS-spy для отладки подписок

Резюмируем

основные правила — всегда отписываться от Observables, очищать таймеры и слушатели событий, завершать Subject'ы и избегать циклических ссылок. Использование async pipe и OnPush стратегии значительно снижает риск утечек.