What is the correct way to avoid using a nested observable subscription in a loop?

651 views Asked by At

I'm using Angular2 and Firebase via Angularfire2 to get some data from a Firebase Realtime Database (basically a large JSON object).

What I have is a poll system. Polls are in a 'Polls' node, poll responses are in a 'Poll-Responses' node. To link these together I use a 'Poll-Response-Links' node.

So basically, to get responses for a poll, I have to get all links and then get the responses from the links.

The below code works, but I feel as though it's terrible practice. Saying this, I have no idea how to do it correctly.

this.teamPollsService.getPollLinkList(id).subscribe((linkList) => {
    this.responses = [];
    for (let link of linkList) {
        this.teamPollsService.getResponse(link['$key']).subscribe((response) => {
            this.responses.push(response);
        });
    }
});

I'm hoping someone could shed some light on the correct way to do this and the reasons behind it?

Any help would be greatly appreciated.

Thanks.

1

There are 1 answers

7
martin On

If you wanted to do this in RxJS way then you can unpack the list with concatAll() and then with concatMap() turn each item into whatever you want with this.teamPollsService.

this.teamPollsService.getPollLinkList(id)
    .concatAll()
    .concatMap(link => this.teamPollsService.getResponse(link['$key']))
    .subscribe(team => console.log(team));

(I didn't test this code)

Operator concatAll() flattens arrays (see RxJS: JSON data with an array, processing each item further in the stream or Merge subarrays using Observables). Then concatMap() reemits a value from the internal Observable.

You could also use mergeMap() that doesn't wait until the previous Observable completed (doesn't guarantee same order of items).