Мне нужен мой угловой сервис, чтобы знать, когда закончились все асинхронные операции компонентов

У меня есть служба angular, которой принадлежит Observable. У меня есть несколько (переменное количество) компонентов, подписанных на него, которые реагируют на выполнение асинхронных операций. Мне нужно, чтобы мой сервис знал, когда закончились все эти асинхронные операции с компонентами.

Это подход к моей ситуации:

Служба фильтрации

...

appliedFilter$: Observable<FormattedFilter[]> = new Observable<FormattedFilter[]>(
    o => (this.appliedFilter = o)
  ).pipe(shareReplay(1));
  private appliedFilter: Observer<FormattedFilter[]>;

  onFiltersApplied(filters: Filter[]): void {
    if (this.appliedFilter) {
      const formattedFilters = this.formatFilters(filters);
      this.appliedFilter.next(formattedFilters);
    }
  }

...

Фильтруемый компонент 1

...

this.filterService.appliedFilter$.subscribe(filters => {
  // multiple pipelined async operations
});

...

Фильтруемый компонент 2

...

this.filterService.appliedFilter$.subscribe(filters => {
  // multiple pipelined async operations
});

...

Фильтруемый компонент 3

...

this.filterService.appliedFilter$.subscribe(filters => {
  // multiple pipelined async operations
});

...

Итак, что мне нужно, так это служба фильтров, чтобы заметить, когда все компоненты применили полученные фильтры через applyFilter$ Observable и когда все отфильтрованные данные наконец загружены.

Цель этого состоит в том, чтобы запретить пользователю обновлять фильтры до того, как все компоненты завершат процесс фильтрации.

Спасибо!

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

Artem Arkhipov 30.05.2019 13:33

@ArtemArkhipov У меня нет особой потребности. Ваш подход кажется хорошим. Но я не знаю, как отменить текущие обновления, поскольку они могут быть довольно сложными.

Mochics 30.05.2019 13:38

Я разместил ответ для вас ниже

Artem Arkhipov 30.05.2019 13:41

Спасибо, попробую.

Mochics 30.05.2019 13:42

Если бы вы могли создать минимальную копию вашего случая, вам было бы легче помочь и показать что-то конкретное.

maxime1992 30.05.2019 13:51

Я обновил свой ответ еще одним примером, дайте мне знать, если это помогло.

Artem Arkhipov 30.05.2019 13:54

@ maxime1992 maxime1992 У меня нет репродукции, потому что я нахожусь на этапе проектирования. Итак, что лучше всего соответствует моим потребностям, так это концептуальный ответ.

Mochics 30.05.2019 13:57

@ArtemArkhipov Я дам вам знать в ближайшие дни. Спасибо!

Mochics 30.05.2019 13:57

@Mochics хорошо, но тогда не могли бы вы рассказать немного больше о том, чего именно вы пытаетесь достичь? «Цель этого состоит в том, чтобы запретить пользователю обновлять фильтры до того, как все компоненты завершат процесс фильтрации», мне не совсем понятно.

maxime1992 30.05.2019 14:03

@ maxime1992 Дело в том, что у меня есть несколько фильтров, которые можно комбинировать, и все эти фильтры обновляют несколько компонентов. Моя цель состояла в том, чтобы заблокировать функцию фильтрации, пока не будут разрешены все ожидающие асинхронные операции. Это оказалось не лучшим подходом, так как, на мой взгляд, АртемАрхипов указал на лучший вариант, заключающийся в отмене всех ожидающих запросов, если выбран новый фильтр. Надеюсь, теперь мои намерения раскрыты.

Mochics 30.05.2019 14:10

О, я вижу, спасибо. Да, ответ Артема кажется подходящим!

maxime1992 30.05.2019 14:15

@maxime1992 Все равно спасибо!

Mochics 30.05.2019 14:18

@ArtemArkhipov Это работает. Хороший подход, спасибо!

Mochics 06.06.2019 15:34
Тестирование функциональных 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
1
13
96
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы уверены, что вам нужно подождать, пока компоненты будут обновлены, вместо того, чтобы обновлять компоненты соответственно, чтобы отфильтровать изменения? В большинстве хороших, удобных приложений подход выглядит иначе: Если какой-то компонент не завершил обновление во время применения нового фильтра - обновления просто отменяются и запускаются заново.

В вашем случае это можно сделать с помощью оператора rxjs переключательКарта. Этот оператор позволяет вам делать именно то, что я только что сказал — отказаться от текущих асинхронных операций и начать новые, если появится новый выброс.

Вот пример:

...

this.filterService.appliedFilter$
    .pipe(
        switchMap(
            filters => { return yourObservableChain()} // chain is your async opeartions
        )
    )
    .subscribe(); // you have only the most relevant values here

...

Итак, что здесь происходит:

  1. Когда применяется новый фильтр, вызывается yourObservableChain (это может быть http-запрос или любые другие вещи, которые вы имели в виду, когда говорили (асинхронные операции).
  2. Если во время этих операций снова применить новый фильтр - старые будут проигнорированы, вызовы будут отменены и начнутся новые операции.
  3. На subscribe придет только самый актуальный результат.

Примечание, этот switchMap должен возвращает наблюдаемое. Вот еще один короткий пример его использования в рамках Angular (с вызовами http).

import { switchMap } from 'rxjs/operators'; // don't forget

... your components code:...

this.triggerSubject$.pipe( // assume this emits with some urls
    switchMap(data => { // assume new url is a prop of data
      return this.http.get(data.URL); // returns observable
    })
).subscribe(results => {
   // having only fresh results here
   // because switchMap cancelled other requests
   console.info(results) // or do whatever you need
})

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