Кэширование нескольких API с помощью RxJS в Angular

У меня есть компонент с несколькими вкладками, по которым пользователи могут перемещаться вперед и назад. Мне нужно загрузить данные из серверной части на первой вкладке. Это создает ненужные HTTP-вызовы каждый раз при повторной инициализации компонента 1. Моя идея состоит в том, чтобы создать службу кэширования, в которой я бы сохранял результат HTTP-вызова, и при повторной инициализации компонента он получал данные из службы (а не из бэкэнда).

Вот еще несколько требований:

  • Сервис должен быть предоставлен в родительском компоненте (когда компонент уничтожается, сервис и кэшированный результат также должны быть уничтожены).
  • Первый HTTP-вызов должен быть инициирован при инициализации компонента 1, а не при инициализации службы.

Каким-то образом это начинает работать, пока я не добавляю Тему для запуска первой загрузки. Теперь он запускает HTTP-вызов каждый раз, когда компонент 1 повторно инициализируется. Демо-версия Stackblitz

Любая помощь приветствуется! Спасибо

Я бы попытался упростить решение, уменьшив количество ненужных субъектов/наблюдаемых. Использование оператора ShareReplay() помогает не вызывать каждый раз бэкэнд: stackblitz.com/edit/…

Serhii Yurko 20.08.2024 15:07
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
1
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Самая простая система «кэширования», которую я когда-либо видел, — это хранение данных в переменных.

data!:any[]
getData()
{
   if (this.data)
      return of(data)

   return this.httpClient.get(...).pipe(
      tap((res:any[])=>this.data=res))
}

Да, это один из вариантов, который мне приходит в голову. Однако вся кодовая база использует декларативный способ. Возможно, есть какое-то более реактивное решение.

Marek 20.08.2024 14:59
Ответ принят как подходящий

Причина ваш код извлекается каждый раз, когда вы загружаете Компонент А, заключается в том, что вы вызываете triggerLoad$.next() каждый раз, когда инициализируется Компонент А!

На самом деле вам не нужен отдельный триггер, вы можете просто объявить один наблюдаемый объект codetables$, который одновременно извлекает и кэширует данные.

  readonly codetables$ = from(this.codetableTypes).pipe(
    mergeMap(codetableType => this.getCodetable(codetableType)),
    scan((acc, current) => ({...acc, ...current}), {} as CodetableOptions),
    shareReplay(1),
    takeUntilDestroyed()
  );

Здесь мы используем shareReplay для кэширования значения. Он ведет себя как ReplaySubject(1); когда потребители подписываются, они немедленно получают самую последнюю информацию.

Вот рабочий Stackblitz

Другие вопросы по теме