Search code examples
javascriptfirebaserxjsangularfire2reactivex

RxJS Waiting for nested observable to filter array data


Having two Observables: foo and bar.

foo will return an array of objects as such [{ id: 1 }, { id: 2 }, ...] (It will return the entire array (using AngularFire .list here))

bar has a stored value for each item returned from foo. The value is stored as an object as such: { id: 2, status: false }.

What needs to be done here is to call foo initially, and in it's map function, I'd like to take out { id: 2 } from the subscribe() method if its matching value in bar's response is false.

In other terms

  1. Watch stream from foo
  2. .map objects and check each object status from bar
  3. bar returns an observable with the value of true or false
  4. .filter foo to take out any object with status as false

I've tried combineLatest, zip and other RxJS methods but not sure that I am doing this correctly. Could someone please show me the correct way or at least point our which methods I should be exploring?

Appreciate the help!

Thanks.

//

.... foo
....... itemId1
....... itemId2

.... bar
....... itemId1: true
....... itemId2: false

Upon subscribing to foo, the array it returns must be filtered to return itemId1 only, because its bar value is true (Both are observables, foo and bar ofc)


Solution

  • Here's a piece of code that gets the job done:

    foo = Rx.Observable.of([
      {id: 1, data: 'foo1'}, 
      {id: 2, data: 'foo2'}, 
      {id: 3, data: 'foo3'}, 
      {id: 4, data: 'foo4'}, 
      {id: 5, data: 'foo5'}, 
      {id: 6, data: 'foo6'}
    ]);
    
    bar = Rx.Observable.of([
      {id: 1, status: false}, 
      {id: 2, status: true}, 
      {id: 3, status: true}, 
      {id: 4, status: false}, 
      {id: 5, status: true}, 
      {id: 6, status: false}
    ]).flatMap(obj => obj);
    
    Rx.Observable.combineLatest(foo, bar)
        .filter(([foo, bar]) => bar.status)
        .map(([foo, bar]) => foo.find(obj => obj.id === bar.id))
      .subscribe(data => {
        console.log(data)
      });