Search code examples
javascriptarrayspromisechaining

JavaScript chaining promises to return an array of all data returned from all promises


I have a scenario where I need to call a "getData" method. This "getData" method will call the server to get items, then for each item i need to get the child items. The "getData" method should return a single array of ALL of the child items in a single array.

For example, i have

  • item1
    • childA, childB, childC
  • item2
    • childD
  • item3
    • childE, childF

I would like to get a single array containing

[childA, childB, childC, childD, childE, childF]

I have tried the following code but this is not quite right.

export function getData() {
    
  return getItems()
    .then((items) =>{
      var promises = [];
      
      items.forEach((item) => {
        
        promises.push(          
            return getChildItems({
                item: `${item}`,
            })
            .then((childItems) => {
              return childItems
            }),       
        );                              
      });   

      return Promise.all(promises)
        .then((allChildItems) => allChildItems);
    });
}

This returns an array where each element is an array. The top level array's number of elements is the number of items. Each child array contains the number of elements matching the number of child items for that item. For example,

[ 
  [childA, childB, childC], 
  [childD], 
  [childE, childF]
]

How can i get it to return a single array like

[childA, childB, childC, childD, childE, childF]

UPDATE:

I found a solution, but I do not this its particularly elegant. In the PromiseAll, i loop over the top level items and them concat the child arrays into a single array and return it,

return Promise.all(promises)
.then((arrayOfChildItemsArrays) => {
  let allChildItems = []
  arrayOfChildItemsArrays.map((childItemsArray) => {
    allChildItems = allChildItems.concat(childItemsArray);
  });
  return allChildItems;
});

Surely there is a nicer way to do this?


Solution

  • You can flatten the array via Array.prototype.flat:

    return Promise.all(promises).then(allChildItems => allChildItems.flat());