Как настроить кэширование данных в Angular?angular-72

Кэширование данных в Angular можно реализовать несколькими способами в зависимости от требований и архитектуры приложения. Рассмотрим основные подходы:

1. Использование сервисов с локальным хранением данных

Самый простой способ - создать сервис, который будет хранить данные в памяти:

@Injectable({ providedIn: 'root' })
export class DataCacheService {
  private cache = new Map<string, { data: any, expires: number }>();

  get(key: string): any | null {
    const item = this.cache.get(key);
    if (!item) return null;

    if (item.expires < Date.now()) {
      this.cache.delete(key);
      return null;
    }

    return item.data;
  }

  set(key: string, data: any, ttl: number = 60000): void {
    this.cache.set(key, {
      data,
      expires: Date.now() + ttl
    });
  }

  clear(key?: string): void {
    if (key) {
      this.cache.delete(key);
    } else {
      this.cache.clear();
    }
  }
}

2. HTTP Interceptor с кэшированием

Более продвинутый способ - реализовать кэширование HTTP-запросов:

@Injectable()
export class CacheInterceptor implements HttpInterceptor {
  private cache = new Map<string, { expires: number, response: any }>();

  constructor(private cacheService: DataCacheService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Кэшируем только GET-запросы
    if (req.method !== 'GET') {
      return next.handle(req);
    }

    const cachedResponse = this.cacheService.get(req.urlWithParams);
    if (cachedResponse) {
      return of(cachedResponse);
    }

    return next.handle(req).pipe(
      tap(event => {
        if (event instanceof HttpResponse) {
          this.cacheService.set(req.urlWithParams, event);
        }
      })
    );
  }
}

Не забудьте зарегистрировать интерсептор в модуле:

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true }
  ]
})
export class AppModule {}

3. Использование библиотек

Для сложных сценариев можно использовать специализированные библиотеки:

  • ngx-cacheable - предоставляет декораторы для кэширования
  • @ngneat/cashew - мощное решение для кэширования HTTP-запросов

Пример с @ngneat/cashew:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { cache } from '@ngneat/cashew';

@Injectable()
export class DataService {
  constructor(private http: HttpClient) {}

  @Cache({
    key: 'users',
    ttl: 3600000 // 1 час
  })
  getUsers() {
    return this.http.get('/api/users');
  }
}

4. Работа с Browser Storage

Для персистентного кэширования между сессиями:

@Injectable()
export class PersistentCacheService {
  constructor() {}

  set(key: string, data: any): void {
    localStorage.setItem(key, JSON.stringify(data));
  }

  get(key: string): any {
    const data = localStorage.getItem(key);
    return data ? JSON.parse(data) : null;
  }
}

5. Оптимизация с помощью RxJS

Использование операторов RxJS для кэширования:

private cache$: Observable<Data[]>;

getData(): Observable<Data[]> {
  if (!this.cache$) {
    this.cache$ = this.http.get<Data[]>('/api/data').pipe(
      shareReplay(1) // Кэшируем последнее значение
    );
  }
  return this.cache$;
}

Важные моменты при реализации кэширования

  1. Инвалидация кэша - важно предусмотреть механизмы сброса кэша при:

    • Изменении данных (POST/PUT/DELETE запросы)
    • Истечении TTL (Time To Live)
    • Явном действии пользователя
  2. Стратегии кэширования:

    • Cache-First (сначала проверять кэш)
    • Network-First (сначала запрашивать с сервера)
    • Stale-While-Revalidate (возвращать кэш, но обновлять его в фоне)
  3. Размер кэша - важно ограничивать размер, чтобы не перегружать память.

Резюмируем

в Angular есть множество способов реализовать кэширование - от простых in-memory решений до сложных стратегий с использованием интерсепторов и специализированных библиотек. Выбор зависит от конкретных требований вашего приложения.