首页 > 解决方案 > 比较 2 不同结构的 Observable

问题描述

我有 2 个来自带有 angularfire 的 firebase 并使用 rxjs 的 observable

private boatsCollection: AngularFirestoreCollection<Boat>;
boats: Observable<Boat[]>;

private bookingsCollection: AngularFirestoreCollection<Booking>;
bookings: Observable<Booking[]>;

结构没有行进,但bookings收集文件ID'S包含有关boat(所以船id)的信息

我想过滤,只留下 ID与预订收集文件值ID匹配的这些文件。

如何使用 rxjs 实现这一点?

ngOnInit() {
  // Subscribe to route params and get user's selected date
  this.sub = this.route.params.subscribe(params => {
    this.date = Number (params['date']);
    // get bookings where selected date exits
    this.bookingsCollection = this.afs.collection<Booking>('bookings', ref => ref.where('date', '==', this.date));
    this.bookings = this.bookingsCollection.valueChanges({ idField: 'id' });
    // Boats Collection
    this.boatsCollection = this.afs.collection<Boat>('boats');
    this.boats = this.boatsCollection.valueChanges({ idField: 'id' });  
 
    combineLatest(this.boats, this.bookings).subscribe(
      ([boats, bookings]) => {
        const bookingIds = bookings.map(booking => booking.boatID);
        const filteredBoats = boats.filter(boat => !(bookingIds.includes(boat.id)));
        console.log(filteredBoats);
      }, 
    ); 
  });
}

标签: angularfirebaseionic-frameworkgoogle-cloud-firestorerxjs

解决方案


有多种方法可以做到这一点。一种方法是使用 RxJScombineLatest函数同时从两个可观察对象获取通知,并使用 Arrayfilterincludes函数过滤数组。

尝试以下

ngOnInit() {
  combineLatest(this.boats, this.bookings).subscribe(
    ([boats, bookings]) => {
      const bookingIds = bookings.map(booking => booking.id);
      this.filteredBoats = boats.filter(boat => !(bookingIds.includes(boat.id)));
      console.log(this.filteredBoats);    // <-- correct
    },
    error => { }
  );

  console.log(this.filteredBoats);    // <-- wrong - will print undefined/previous value
}

现在,combineLatest它将为它的任何源 observables 的每次发射发射。此外,所有源 observables 都应该至少发出一次。

您可以根据需要使用 RxJSzipforkJoin函数。虽然 rememberforkJoin只会在所有源 observables 完成时才会发出。

更新:异步数据

filteredBoats是异步分配的。这意味着console.log在订阅之外执行时,filteredBoats还没有任何值。console.log应该在订阅内。

更多关于异步数据的信息在这里


推荐阅读