How to combine the results of two observable in angular?

Viewed 79076

How to combine the results of two observable in angular?

this.http.get(url1)
    .map((res: Response) => res.json())
    .subscribe((data1: any) => {
        this.data1 = data1;
    });

this.http.get(url2)
    .map((res: Response) => res.json())
    .subscribe((data2: any) => {
        this.data2 = data2;
    });

toDisplay(){
  // logic about combining this.data1 and this.data2;
}

The above is wrong, because we couldn't get data1 and data2 immediately.

this.http.get(url1)
    .map((res: Response) => res.json())
    .subscribe((data1: any) => {
    this.http.get(url2)
        .map((res: Response) => res.json())
        .subscribe((data2: any) => {
            this.data2 = data2;

            // logic about combining this.data1 and this.data2
            // and set to this.data;
            this.toDisplay();
        });
    });

toDisplay(){
  // display data
  // this.data;
}

I can combine the results in the subscribe method of the second observable. But I'm not sure if it's a good practice to achieve my requirement.

Update:
Another way I found is using forkJoin to combine the results and return a new observable.

let o1: Observable<any> = this.http.get(url1)
    .map((res: Response) => res.json())

let o2: Observable<any> = this.http.get(url2)
    .map((res: Response) => res.json());

Observable.forkJoin(o1, o2)
  .subscribe(val => {  // [data1, data2]
    // logic about combining data1 and data2;
    toDisplay(); // display data
});

toDisplay(){
  // 
}
5 Answers

We can combine observables in different ways based on our need. I had two problems:

  1. The response of first is the input for the second one: flatMap() is suitable in this case.
  2. Both must finish before proceeding further: forkJoin()/megre()/concat() can be used depending on how you want your output.

You can find details of all the above functions here. You can find even more operations that can be performed to combine observables here.

TRY with forkJoin if it's not working then give this a try combineLatest() What it do - it combine the last emitted value from your stream array into one before completion of your stream array.

Observable.combineLatest(
        this.filesServiceOberserval,
        this.filesServiceOberserval,
        this.processesServiceOberserval,
    ).subscribe(
        data => {
          this.inputs = data[0];
          this.outputs = data[1];
          this.processes = data[2];
        },
        err => console.error(err)
    );

You can merge multiple observables into a single observable and then reduce the values from the source observable into a single value.

const cats = this.http.get<Pet[]>('https://example.com/cats.json');

const dogs = this.http.get<Pet[]>('https://example.com/dogs.json');

const catsAndDogs = merge(cats, dogs).pipe(reduce((a, b) => a.concat(b)));
Related