发布
社区首页 >问答首页 >即使等待Promise.all()

即使等待Promise.all()
EN

Stack Overflow用户
提问于 2021-10-08 00:07:14
回答 1查看 618关注 0票数 1

在等待Promise.all()之后,我很难理解为什么我还有悬而未决的承诺。

在下面的示例中,我通过使用.map()对数组的每个元素调用异步函数来创建一个承诺数组。

现在,为什么承诺仍然是悬而未决的呢?我现在的理解是:

  • 一旦来自then()的承诺得到解决,storeData()就会触发
  • 一旦返回storeData()newDataArray就会解析
  • 一旦解决了newDataArray中的所有承诺,或者一旦第一个承诺被拒绝,就会返回promisesArray
代码语言:javascript
代码运行次数:0
复制
storeData(OldDataArray).then(values => console.log(values))
// console shows:
// { id: 1, data: Promise { <pending> } },
// { id: 2, data: Promise { <pending> } }
代码语言:javascript
代码运行次数:0
复制
const storeData = async (OldDataArray) => {
  try {
      const promisesArray = OldDataArray.map((item) => {
      let newData = downloadMoreDetails(item.id, item.group); //async function, see below
      return {
        id: item.id,
        data: newData,
      };
    });
    const newDataArray = await Promise.all(promisesArray);  // <-- I'm awaiting all promises to complete before assigning to newDataArray
    return newDataArray;
  } catch (error) {
    console.log(error)
  }
};
代码语言:javascript
代码运行次数:0
复制
const downloadMoreDetails = async (id, group) => {
  const response = await fetch(
    `example.com/id/group.xml`
  );
  if (!response.ok) {
    throw new Error(`HTTP error ${response.status}`);
  }

  const str = await response.text();
  const json = convert.xml2json(str, {
    compact: true,
    spaces: 2,
  });
  return json;
};
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-08 00:28:27

newData是一个承诺,但你没有等待承诺。相反,您正在等待一个对象数组( {id: item.id, data: newData } ),该数组中包含了它的承诺。Promise.all()不会在这些对象内部寻找承诺,然后等待承诺。它只看到一个简单的对象数组,这意味着它没有什么可做的。您可以通过这样做来解决这个问题:

代码语言:javascript
代码运行次数:0
复制
const storeData = async (OldDataArray) => {
  try {
    const promisesArray = OldDataArray.map(async (item) => {
        let newData = await downloadMoreDetails(item.id, item.group); //async function, see below
        return {
          id: item.id,
          data: newData,
        };
    });
    return Promise.all(promisesArray);
  } catch (error) {
    // log and rethrow error so the caller gets the rejection
    console.log(error);
    throw error;
  }
};

这将.map()回调更改为async。做两件有益的事。首先,这意味着来自.map()的结果数组将是一个承诺数组,因为async回调总是返回一个承诺。其次,它允许在回调中使用await,这样就可以用实际的数据填充返回的对象,而不是承诺。

然后,来自return回调内部的async将导致该值成为async函数返回的承诺的解析值。

注意,您也可以在不添加像这样的async/await的情况下完成它:

代码语言:javascript
代码运行次数:0
复制
const storeData = (OldDataArray) => {
    const promisesArray = OldDataArray.map((item) => {
       return downloadMoreDetails(item.id, item.group).then(newData => {
          return {
            id: item.id,
            data: newData,
          };
       });
    });
    return Promise.all(promisesArray).catch(error => {
      // log and rethrow error so the caller gets the rejection
      console.log(error);
      throw error;
    });
};

在这个版本中,您直接从.map()回调返回一个承诺,并确保该承诺解析为您的数据对象。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69489072

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档