Убьет ли перезапись наблюдаемой переменной текущих подписчиков?

Я хочу иметь возможность кэшировать HTTP-вызов, но также принудительно обновлять кеш. Моя служба выглядит так:

@Injectable()
export class UserService {
  private currentUser$: Observable<User>;

  constructor(private http: HttpClient) { }

  getCurrentUser(force = false): Observable<User> {
    if (!this.currentUser$ || force) {
      this.currentUser$ = this.http.get<User>(`${environment.API_URL}/profiles/me`)
        .pipe(
          shareReplay(CACHE_SIZE)
        );
    }
    return this.currentUser$;
  }
}

Если я вызываю getCurrentUser(true), переменная currentUser$ перезаписывается. Боюсь, это уничтожит всех существующих подписчиков. Это правда? Как их сохранить?

Тестирование функциональных 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
4
0
461
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Представьте, что this.currentUser$ указывает на объект в куче. Ваш метод возвращает копию ссылки на this.currentUser$. Таким образом, все подписанные наблюдатели будут продолжать слушать их (пока все они не откажутся от подписки и Observable не соберет мусор).

Если вы вызываете метод с помощью "force", this.currentUser$ просто укажет на другой Observable<User> где-то еще в куче.

Так вы говорите, что у меня в памяти будет два Observable? Один указан переменной, а другой не имеет переменной? Вы также говорите, что, поскольку у первого Observable все еще есть подписчики, он не собирает мусор? Похоже на утечку памяти.

adam0101 26.09.2018 23:35

Кроме того, будут ли подписчики первого Observable больше не получать обновления, поскольку нет переменной, в которую можно было бы отправлять новые значения?

adam0101 26.09.2018 23:38

Это правильные выводы :). Конечно, если вы передадите этот Observable, какой-то другой объект может передать новые значения. Но я полагаю, что это не так. Также нужно быть осторожным с утечками памяти. Всегда откажитесь от подписки на свои Observables. По этому поводу есть много вопросов / ответов.

highlysignificantbit 27.09.2018 00:07

Я приму ваш ответ, поскольку он отвечает на мой вопрос, но не могли бы вы взглянуть на мое решение и сообщить мне, если у вас возникнут какие-либо проблемы с ним?

adam0101 27.09.2018 00:17

У меня недостаточно кредитов, чтобы прокомментировать ваш код ниже :). Но посмотрите на rxjs .take (1), чтобы автоматически отказаться от подписки после того, как вы что-то получили.

highlysignificantbit 27.09.2018 00:31

Кроме того, разделите эти методы на два отдельных метода. A) Действие: один извлекает пользователей и помещает их в тему и B) для «наблюдателей»: метод, возвращающий переменную-член, такую ​​как userObs$ = currentUser$.asObservable().

highlysignificantbit 27.09.2018 00:36

Спасибо. Я разделил методы. Я также удалил логику отказа от подписки для http-вызова. Судя по всему HttpClientделает это для тебя

adam0101 27.09.2018 00:53

Я собираюсь опубликовать здесь то, что я сделал, на случай, если это поможет кому-то еще. Вместо этого я возвращаю один экземпляр BehaviorSubject и просто вставляю в него новые значения всякий раз, когда мне нужно «принудительно» получить текущего пользователя. Я также добавил флаг fetchingCurrentUser, чтобы я не делал несколько вызовов, пока я жду завершения первого вызова API.

Пожалуйста, дайте мне знать, если кто-нибудь увидит какие-либо проблемы с этим или у вас есть идеи, как сделать это очиститель. Спасибо.

@Injectable()
export class UserService {
  private currentUser$: BehaviorSubject<User>;
  private fetchingCurrentUser: boolean;

  constructor(private http: HttpClient) {
    this.currentUser$ = new BehaviorSubject(null);
  }

  getCurrentUser(force = false): Observable<User> {
    if (this.currentUser$.value == null || force) {
      this.refreshCurrentUser();
    }
    return this.currentUser$.asObservable();
  }

  refreshCurrentUser() {
    if (!this.fetchingCurrentUser) {
      this.fetchingCurrentUser = true;
      this.http.get<User>(`${environment.API_URL}/profiles/me`)
        .subscribe(x => {
          this.currentUser$.next(x);
          this.fetchingCurrentUser = false;
        });
    }
  }

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