Search code examples
angularasynchronousrxjsfetchhttprequest

How can I make multiple nested http request in RxJs?


I'm newbie to RxJs. I could not find how to do it. I have a large number of nested http requests in my master data. And I want to get all the http requests and combine them all in my main stream.

My example main stream data as:

[
    {
        id: '123',
        name: 'nameVal1',
        salary: [
            { href: 'http://example.com/salary/1' },
            { href: 'http://example.com/salary/2' }
        ],
        address: {
            href: 'http:/example.com/address'
        }
    },

    {
        id: '456',
        name: 'nameVal2',
        salary: {
            href: 'http://example.com/salary/1'
        },
        address: {
            href: 'http:/example.com/address'
        }
    }
];

Example salary object:

{
    salary: '1000€',
    month: 2
}

Example address object:

{
    country: 'UK',
    city: 'London',
    postalCode: '123'
}

My main stream is array of objects like above and after get the main stream, I want to get all nested data and combine them all the main stream like that:

[
{
    id: '123',
    name: 'nameVal1',
    salary: [
        {
            salary: '1000€',
            month: 2
        },
        {
            salary: '500€',
            month: 3
        }
    ],
    address: {
        country: 'UK',
        city: 'London',
        postalCode: '123'
    }
},

{
    id: '456',
    name: 'nameVal2',
    salary: [
        {
            salary: '2000€',
            month: 3
        }
    ],
    address: {
        country: 'UK',
        city: 'London',
        postalCode: '456'
    }
}
];


this.service.mainHttpReq().pipe(
    map(users => {
        users.salary.forEach(salaryItem => { 
            return fetch(salaryItem.href); 
        });
        

    })
).subscribe(usersData => {
   console.log('Users Data :', usersData);
});

Solution

  • Use forkJoin to fetch data in parallel.

    mainStream.pipe(
      // fetch data for every person
      switchMap(persons => forkJoin(
        persons.map(person => getPersonData(person))
      ))
    );
    
    // get data for a single person
    function getPersonData(person): Observable<any> {
      // the salary data as an observable
      const salaryData = forkJoin(person.salary.map(({ href }) => getSalaryData(href));
      // the address data as an observable
      const addressData = getAddressData(person.address.href);
      // combine salary and address data
      return forkJoin(salaryData, addressData).pipe(
        // map salary and address data to a person object with this data
        map(([ salary, address ]) => ({ ...person, salary, address }))
      );
    }