Sumit Ridhal
Sumit Ridhal

Reputation: 1419

rxjs forkJoin nested observable inside another observable

There is two set of observable (network requests). After first observable resolved, i need to forkJoin multiple observable. But in return instead of data i'm getting a Subscriber.

Kindly check the thid fiddle https://stackblitz.com/edit/zj3mhp?file=index.ts

import { forkJoin, of, timer } from "rxjs";
import { map } from "rxjs/operators";

let array = [of({ data: [1] }), of({ data: [2] })];
const init = of({ pages: 2 });

function gerData() {
  const observable = forkJoin(array);
  return init.pipe(
    map(data => {
      return observable.subscribe(data => {
        const arr = [];
        data.forEach(x => {
          arr.push(...x.data);
        });
        console.log('array', arr);
        return arr;
      });
    })
  );
}



gerData().subscribe((data) => {
  console.log('final data: ', data);
})

Upvotes: 1

Views: 4737

Answers (3)

Fan Cheung
Fan Cheung

Reputation: 11380

Once you subscribe to an observable it starts executing and is turned into an subscription, you should return observable and use switchMap to run that observable instead. Please try the following:

function gerData() {
  return init.pipe(switchMap(data=>
    forkJoin(array).pipe(map(arr=>arr.map(item=>item.data)))
  ));
}

Upvotes: 0

Ashish Ranjan
Ashish Ranjan

Reputation: 12970

You can use mergeMap() instead of map(), returning a subscription is not going to help.

Whatever we return in a map() that will be the value received in the success callback of a subscription. We can not retrieve the values from a subscription object.

In mergeMap we return an Observable which will be merged with the parent observable and we can get the value of the merged observable using a single subscription.

import { forkJoin, of, timer } from "rxjs";
import { map, mergeMap } from "rxjs/operators";

let array = [of({ data: [1] }), of({ data: [2] })];
const init = of({ pages: 2 });

function gerData() {
  const observable = forkJoin(array);
  return init.pipe(
    mergeMap(data => {
      return observable.pipe(map(data => {
        const arr = [];
        data.forEach(x => {
          arr.push(...x.data);
        });
        console.log('array', arr);
        return arr;
      }));
    })
  );
}



gerData().subscribe((data) => {
  console.log('final data: ', data);
})

https://stackblitz.com/edit/zj3mhp-elrkur?file=index.ts

Upvotes: 3

Sam
Sam

Reputation: 632

You could do something like

function gerData() {
  const observable = forkJoin(array);
  return init.pipe(
    switchMap(() => observable),
    map(res => res.reduce((prev, next) => prev.concat(next.data), []))
  );
}

gerData().subscribe(data => {
  console.log("final data: ", data);
});

Upvotes: 2

Related Questions