简体   繁体   中英

Angular 2 combining of multiple (similar) observables

I've found many examples detailing how multiple observable calls can be combined into a single Observable call, but from what I have found, these calls always assume at least one of the following:

1: the number of calls is known 2: the number of calls is fixed 3: the calls are different objects combined into one. (as in arg1 => call1, arg2 => call2)

But I've failed to find any decent information as to how to handle the combination of Observables when these calls are made dynamically or when rather than mapping results to different variables, you wish to expand on a list you're trying to collect.

To give an use-case in which this could apply: An user can sign up to several "groups" of products. Each group is linked with an ID, which is used to fetch the products from a remote service. The group is to fetch all products from all groups, join them together, and display them to the user.

The most logical solution to me seems to be to wait until all calls are completed while gathering the results in another list, and from there it would be easy to compile these lists into a single, wanted result, but I've been unable to find a way to effectively achieve this- And am curious to hear if others might have ideas for how to best tackle this problem.

let responses = Array<Observable<Articles>>
    for (let id of subscriptions) {
        let response = this.http.get(producturl + id, headers).map(
            //insert mapping...
        );
    responses.push(response);
}

from here I have tried to use .merge() to try and merge the "responses" together but feel like I'm not familiar enough with the command/ misusing it. I've also tried iterating over the Observables and subscribing to them in turn, but this seems both sub-optimal and did not produce the wanted results. I've tried more, but these two options seem to me to be most likely to be on the right track to a proper solution... If more code is needed to see where the potential issue might lie, I'll gladly share- And thanks for any input.

You can use forkJoin together with a normal reduce :

let responses: Array<Observable<Articles>> = [];
for (let id of subscriptions) {
    let response: Observable<Articles> = this.http.get(producturl + id, headers).map();
    responses.push(response);
}

Observable.forkJoin(responses)
   .map(response => response.reduce((a,b) => {return a.concat(b)}))
   .subscribe((response: Articles[]) => {
       console.log(response);
      //output is a flat array of all Articles
});

Don't forget to add the rxjs operator:

import 'rxjs/add/observable/forkJoin';

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM