【问题标题】:Unsure how to resolve a pending promise?不确定如何解决待处理的承诺?
【发布时间】:2021-03-27 15:23:27
【问题描述】:

我正在遍历一些数据并获取单个导航项。

如果我在getNavItems 函数中的return 之前console.log(navItems),它会记录我期望的所有内容。

但是,如果我在返回 getFooterData 之前登录 footerData,我会在我的项目中返回一个未解决的承诺

[
  { heading: 'Heading 1', items: Promise { <pending> } },
  { heading: 'Heading 2', items: Promise { <pending> } },
  { heading: 'Heading 3', items: Promise { <pending> } },
]

我期待的更像是:

[
  { heading: 'Heading 1', items: [ {data: 1}, {data: 2}, {data: 3} ] },
]
const getNavitems = async (navItemList) => {
  const navItemIds = navItemList.map(({ sys: { id } }) => id);

  const navItemData = await Promise.all(
    navItemIds.map((id) => client.getEntry(id))
  );

  const navItems = navItemData.map((item) => item.fields);

  return navItems;
};

const getFooterData = async () => {
  const footerDataCollection = await client.getEntry('abcxyz123');

  const footerData = Object.entries(footerDataCollection.fields.sections).map(
    (item) => {
      return {
        heading: item[1].fields.heading,
        items: (() => getNavitems(item[1].fields.item_list))()
      };
    }
  );

  return footerData;
};

任何帮助都会很棒,因为我已经为此努力了好几个小时了!

【问题讨论】:

  • 类似于您如何收集一系列承诺并等待它们为navItemData 完成,因此您也必须等待项目中的承诺。
  • 你试过(await client).getEntry('abcxyz123');吗?或(await (await client).json()).getEntry('abcxyz123');
  • 可以试试return await Promise.all(footerData);
  • @KevinB 我在哪里需要这样做,对不起!我不确定我是否 100% 关注!
  • @StackSlave navItems 是一个只有 2 个字符串的对象数组。 [ { a: 'hello', b: 'world' } ]

标签: javascript ecmascript-6 async-await es6-promise map-function


【解决方案1】:

使用循环的解决方案。 (Array.prototype.mapawait 很棘手)

我没有测试过这个,因为我没有办法。

const getNavitems = async (navItemList) => {
  const navItemIds = navItemList.map(({ sys: { id } }) => id);

  const navItemData = await Promise.all(
    navItemIds.map((id) => client.getEntry(id))
  );

  const navItems = navItemData.map((item) => item.fields);

  return navItems;
};

const getFooterData = async () => {
  const footerDataCollection = await client.getEntry('abcxyz123');

  const footerData = Object.entries(footerDataCollection.fields.sections);

  const items = await Promise.all(footerData.map(item => getNavitems(item[1].fields.item_list)));

  for (let i = footerData.length; i--;) {
      footerData[i] = {
          heading: footerData[i][1].fields.heading,
          items: items[i]
      }
  }

  return footerData;
};

【讨论】:

  • 由于在非异步函数中使用await,这应该会引发错误。使地图回调异步需要额外的代码来从中获取预期的数组。
  • 我也注意到了,所以我重写了它,使它使用循环
【解决方案2】:

也许items: (() =&gt; getNavitems(item[1].fields.item_list))() 试试items: await getNavitems(item[1].fields.item_list)。匿名函数到底是干什么用的?

const footerData = await Promise.all(Object.entries(footerDataCollection.fields.sections).map(
    async (item) => {
      return {
        heading: item[1].fields.heading,
        items: await getNavitems(item[1].fields.item_list)
      };
    }
  ));

【讨论】:

  • getNavitems 已经是async。 OP 只需要items: ()=&gt;getNavitems(item[1].fields.item_list),但这似乎不是问题。
  • 会像这样在 Array.prototype.map 中使用 await 会导致所有的 Promise 一个接一个地依次解决吗?还是编译器对其进行了优化,以便并行解决承诺?
  • 会按顺序执行,但map不会等待结果,所以执行的函数的结果可能以不同的顺序准备好(如并行)。 Promise.all([...]) 等待所有功能完成。
【解决方案3】:

items: (() =&gt; getNavitems(item[1].fields.item_list))()中,需要插入另一个await

items: (async () => await getNavitems(item[1].fields.item_list))()

getNavItems 是一个异步函数。因此,必须使用await 来获取返回值。

【讨论】:

  • 同样的结果? 我也确实在这里收到了 eslint 警告! >在返回值上重复使用await。 eslint (no-return-await)
  • @Nick Try items: await getNavitems(item[1].fields.item_list)?
  • .map 不会等你的 await
猜你喜欢
  • 2022-01-22
  • 1970-01-01
  • 2020-04-21
  • 1970-01-01
  • 2016-12-13
  • 2018-03-19
  • 1970-01-01
  • 2019-04-29
  • 2019-06-16
相关资源
最近更新 更多