JavaScript 将承诺链接到 return 所有数据的数组 return 来自所有承诺

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

我有一个场景需要调用“getData”方法。这个“getData”方法将调用服务器来获取项目,然后对于每个项目,我需要获取 child 个项目。 “getData”方法应该 return 单个数组中所有 child 项的单个数组。

比如我有

我想要一个包含

的数组
[childA, childB, childC, childD, childE, childF]

我试过下面的代码,但这不太正确。

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);
    });
}

这个return是一个数组,其中每个元素都是一个数组。顶级数组的元素数是项目数。每个 child 数组包含与该项目的 child 项目数相匹配的元素数。例如,

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

我怎样才能把它变成 return 像

这样的单个数组
[childA, childB, childC, childD, childE, childF]

更新:

我找到了一个解决方案,但我认为它不是特别优雅。在 PromiseAll 中,我循环遍历顶级项目,它们将 child 数组连接成一个数组,然后 return 它,

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

当然有更好的方法来做到这一点?

您可以通过 Array.prototype.flat:

展平数组
return Promise.all(promises).then(allChildItems => allChildItems.flat());

一种解决方案是保留当前代码并在结果上调用 flat(Infinity)。这会给你一个扁平化的数组。这是一个略微缩短的版本:

export function getData() {
  return getItems()
    .then((items) => Promise.all(items.map(item => getChildItems({item: `${item}`))))
    .then((childArrays) => {
      return childArrays.flat(Infinity);
    });
}

我在那里使用了 Infinity,但默认值为 1,这可能足以满足您的用例。

或者,您可以自己遍历它们(flat 相对较新的,但也很容易填充):

export function getData() {
  return getItems()
    .then((items) => Promise.all(items.map(item => getChildItems({item: `${item}`))))
    .then((childArrays) => {
      const result = [];
      for (const array of childArrays) {
          result.push(...array);
      }
      return result;
    });
}