rxjs过滤可观察流未正常工作的意外结果

时间:2018-06-14 16:22:11

标签: angular 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;
              });
            })
          )

        );
      })
    );
  }
}

它有效(我的意思是没有错误),但过滤后的observable表现得很奇怪,结果并不像我期望的那样。

在预览图片上:

广告1.我第一次选择时结果是正确的。

广告2.然后,当我更改minPrice时,它似乎忽略了maxPrice

广告3.(不在预览版img中)然后,当我更改maxPrice时,它会忽略minPrice等等...

Preview

什么可能导致此行为以及如何解决此问题?

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
    );

1 个答案:

答案 0 :(得分:2)

问题不在你的filter中,因为这只是简单的Array.filter()而且我没有看到任何问题。

问题可能是merge运算符。如果孩子merge中的任何一个发出,Observables将会发出。 E.x:priceMin然后发出merge后发出priceMax然后merge发出priceMax值。

要在observable发出时获取这两个值,您可能希望将merge更改为combineLatest。请务必稍微更改一下逻辑,因为combineLatest[valueFromObs1, valueFromObs2]作为Array返回,与merge不同。