Rxjs Фильтр наблюдаемого потока работает некорректно неожиданные результаты

В моем компоненте есть два поля формы. Первый - выбрать priceMin, второй - выбрать priceMax.

Затем у меня есть наблюдаемое, которое я хочу отфильтровать.

export class ListingsComponent implements OnInit {
  listings$: Observable<Listing[]>;
  filterForm: FormGroup;

  constructor(private firestore: FirestoreService, private fb: FormBuilder) {}

  get priceMin() {
    return this.filterForm.get('priceMin');
  }
  get priceMax() {
    return this.filterForm.get('priceMax');
  }

  ngOnInit() {
    this.filterForm = this.fb.group({
      priceMin: [null],
      priceMax: [null]
    });

    this.listings$ = this.firestore.getListings().pipe(
      switchMap(listings => {
        return merge(

          this.priceMin.valueChanges.pipe(
            map(priceMin => {
              return listings.filter(listing => {
                return listing.profile.price.hour >= priceMin;
              });
            })
          ),

          this.priceMax.valueChanges.pipe(
            map(priceMax => {
              return listings.filter(listing => {
                return listing.profile.price.hour <= priceMax;
              });
            })
          )

        );
      })
    );
  }
}

Он работает (я имею в виду отсутствие ошибок), но отфильтрованное наблюдаемое ведет себя странно, и результат не такой, как я ожидал.

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

Объявление 1. Результаты верны, когда я выбираю впервые.

Объявление 2. Затем, когда я меняю minPrice, похоже, он игнорирует maxPrice.

Объявление 3. (Нет в превью img) Затем, когда я меняю maxPrice, он игнорирует minPrice и так далее ...

Rxjs Фильтр наблюдаемого потока работает некорректно неожиданные результаты

Что может вызвать такое поведение и как это исправить?

Working code:

this.listings$ = combineLatest(this.priceMin.valueChanges, this.priceMax.valueChanges).pipe(
      switchMap(price => {
        return this.firestore.getListings().pipe(
          map(listings => {
            return listings.filter(listing => {
              return (
                listing.profile.price.hour >= price[0] && listing.profile.price.hour <= price[1]
              );
            });
          })
        );
      })
    );

Наконец, я использовал Behavior Subject для хранения начального значения фильтров.

this.priceMin.valueChanges.pipe(map(value => this.filterPriceMin.next(value))).subscribe();

const filters$ = combineLatest(
      this.filterPriceMin, // filter 0
      this.filterPriceMax // filter 1
    );

Единственная проблема с рабочим кодом заключается в том, что он не будет отображать никаких элементов, пока оба наблюдаемых объекта в combLatest не выдадут значение. Но это не часть этого вопроса.

Rafff 14.06.2018 20:00
Тестирование функциональных 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
1
667
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Проблема не в вашем filter, потому что это просто Array.filter(), и я не вижу в нем ничего плохого.

Вероятно проблема в операторе merge. merge будет излучать, если один из дочерних Observables излучает. E.x: priceMin излучает, затем излучает merge, затем излучает priceMax, затем merge излучает значение priceMax.

Чтобы получить оба значения при излучении наблюдаемого, вы можете изменить merge на combineLatest. Не забудьте немного изменить свою логику, потому что combineLatest возвращает [valueFromObs1, valueFromObs2] как Array, в отличие от merge.

Спасибо за подсказку. Тогда я попробую с combineLatest и дам вам знать.

Rafff 14.06.2018 18:40

Ага, наверное, другой map после combineLatest сделает это;)

Chau Tran 14.06.2018 18:44

ОК. Кажется, сейчас работает. Я обновил свой вопрос ответом. Спасибо :)

Rafff 14.06.2018 18:58

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