4
votes

I have the following code which returns an observable with the item details for each item key:

this.list = this.af.database.list("API_URL")
      .map((ItemKeys) => {
        return ItemKeys.map((ItemKey) => {
          return this.af.database.object(API_URL + "/" + ItemKey); //I need this as the object (not observable)
        });
      }).subscribe((items) => {
        this.lineData = items; //A list of observables
      });

The code itereates over each item key and gets the item data from another endpoint. The problem is that it retruns an observable of each item data, and I need it in an object (the observable result).

I tried to return the subscription result with the following code, but then all my items data are empty (undefined):

this.list = this.af.database.list("API_URL")
      .map((ItemKeys) => {
        return orderItemKeys.map((ItemKey) => {
          this.af.database.object("API_URL" + "/ItemKey.$key) // So I tried to subscribe to this..
          .subscribe((data) => {
            return data;
          });
        });
      }).subscribe((items) => {
        this.lineData = items; // A list with undefined items
      });

How I can return the item data object as an object and not as observable of an object in my case?

2

2 Answers

1
votes

Don't return a subscription (from subscribe) inside an operator. That's probably not want you intend to do.

For the inner part, where you retrieve a list of objects, you should be able to turn an array of observables created from Array#map() into a higher-order observable with Observable#from(). You need mergeAll() to take this series of observables back to a single stream, then collect all emitted items into an array with toArray(). Then you extract the last observable with mergeMap().

this.list = this.af.database.list("API_URL")
  .mergeMap((ItemKeys) => {
    return Observable.from(ItemKeys.map((ItemKey) => {
      return this.af.database.object(API_URL + "/" + ItemKey);
    })).mergeAll().toArray();
  })
  .subscribe((items) => {
    this.lineData = items;
  });
0
votes

You should replace map with the flatMap, as it is capable of flattening Observable<Observable<T>>.

var responseStream = requestStream
    .flatMap(function(requestUrl) {
        return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
});

responseStream.subscribe(() => {});

Trying to adapt and simplify your code to this

const databaseList = () => Rx.Observable.from(['a6b54x4', '1e23sa4q']);
const databaseObject = (id) => Rx.Observable.of({ id, status: 'ok' })

databaseList() 
   .flatMap(x => databaseObject(`id/${x}`))
   .reduce((x, y) => x.concat(y), [])
   .subscribe(console.log);

Basically, it still flattens Observable<Observable<T>> and then using reduction, merges everything into a result array.

https://jsfiddle.net/6pLpo3cp/