Picci
Picci

Reputation: 17752

combine Observable and Promise

I have a service, MyService, which has a method getList() which returns an Observable of an array of Items, something like

getList(): Observable<Item[]>

Once the list is retrieved, then each Item needs to go through a second method of MyService, fillItem(Item). This method issues a request to some back end which returns a Promise, something like:

fillItem(item: Item) {
   BackEnd.retrieveDetails(item.id)
          .then(data => item.data = data);
}

What I need is to combine the above two methods so that MyService is able to return an Observable which emits the list of Items once all of them have been filled with their data (i.e. once all Promises have been resolved).

What I have tried so far is something along these lines

fillAll(items: Item[]) {
   const promises = [];
   for (let i = 0; i < items.length; i++) {
      const item = items[i];
      promises.push(this.fillItem(item));
   }
   const subject = new Subject<Item[]>();
   Promise.all(promises).then(res => {
                subject.next(items);
            },
            err => {
                subject.error(err);
            });
   return subject.asObservable();
}

getListWithFilledItems() {
   return this.getList()
              .map(items => this.fillAll(items))
}

Unfortunately, if I do so, the method getListWithFilledItems() returns an Observable<Observable<Item[]>> and not, as I hoped, an Observable<Item[]>.

Any suggestion on how to change the code so that the method getListWithFilledItems() returns an Observable<Item[]> would be appreciated.

Upvotes: 0

Views: 1133

Answers (1)

martin
martin

Reputation: 96891

I think instead of .map(items => this.fillAll(items)) you can use just mergeMap():

.mergeMap(items => this.fillAll(items))

This will subscribe to the Observable returned from fillAll() and reemit its value when it's ready.

Btw, be aware that you're not calling complete() on the internal subject so the Observable chain isn't disposed properly (however it might not event matter in your use-case).

Upvotes: 1

Related Questions