сравните 2 наблюдаемых с другой структурой - PullRequest
1 голос
/ 04 августа 2020

У меня есть 2 наблюдаемых, исходящих от firebase с angularfire и использующих структуры rx js

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

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

, но bookings документы коллекции имеют ID'S, содержащие информацию о boat (так что лодка id)

Я хочу отфильтровать лодки и оставить только те документы, идентификаторы которых не совпадают с документами сбора бронирований ID значением.

Как этого можно достичь с помощью rx js?

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

1 Ответ

1 голос
/ 04 августа 2020

Есть несколько способов сделать это. Один из способов - получать уведомления от обоих наблюдаемых одновременно с помощью функции Rx JS combineLatest и фильтровать массивы с помощью Array filter и includes function.

Попробуйте следующее:

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 будет излучать при каждом излучении любой из наблюдаемых источников. Кроме того, все исходные наблюдаемые должны генерироваться хотя бы один раз.

Вы можете использовать функции Rx JS zip или forkJoin в зависимости от ваших требований . Хотя помните, что forkJoin будет выдавать только тогда, когда все исходные наблюдаемые будут завершены.

Обновление: Асинхронный c данные

filteredBoats назначается асинхронно. Это означает, что к моменту выполнения console.log вне подписки filteredBoats еще не имеет значений. console.log должен быть внутри подписки.

Подробнее об asyn c data здесь .

...