【问题标题】:Return value after all the promises are resolved解决所有承诺后的返回值
【发布时间】:2019-10-01 00:37:09
【问题描述】:

我正在编写一个 nodejs 代码,该代码从站点获取数据、解析它、查找特定数据并为之前获取的数据获取其他内容。但是最终的 return 语句返回时没有从第二个 API 调用中获取值。

我尝试实现异步等待,但我不确定我必须将它们准确地放在哪里。

const getMainData = async val => {
  let result = [];

  //get xml data from the API
  const xmlData = await getSiteContent(`value`); //axios call

  parseString(xmlData, (err, json) => { //convert xml to json

    const { entry } = json.feed; // array of results.
    result = entry.map(report => {
      const secondInfo = getSomeMoreData(report.something); //axios call
      const data = {
        id: report.id,
        date: report.date,
        title: report.title
      };
      data.info = secondInfo;
      return data;
    });

  });


  return { result };
};

我期待函数返回包含 id、日期、标题和信息的数组 result。但我将 info 设为 null,因为它会转到另一个执行另一个 API 调用的函数。

【问题讨论】:

标签: node.js promise async-await


【解决方案1】:

尝试将parseString 包装在promise 中,这样你就可以await 得到结果,然后将entry.map 回调一个async 函数,这样你就可以使用await 关键字等待结果axios 获取。

async function xml2json(xml) {
  return new Promise((resolve, reject) => {
    parseString(xml, function (err, json) {
      if (err)
        reject(err);
      else
        resolve(json);
    });
  });
}

const getMainData = async val => {
  //get xml data from the API
  const xmlData = await getSiteContent(`value`); //axios call

  const json = await xml2json(xmlData);
  const { entry } = json.feed; // array of results

  const result = await Promise.all(
    entry.map(async report => {
      const secondInfo = await getSomeMoreData(report.something); // axios call
      const data = {
        id: report.id,
        date: report.date,
        title: report.title,
      };
      data.info = secondInfo;
      return data;
    })
  )

  return { result };
}

让我知道这是否有效。如果没有,我可以尝试进一步帮助您。

【讨论】:

  • entry.map() 的 callback() 是一个异步函数,这意味着结果将是一个充满承诺的数组,对吧?所以它不应该需要解决吗,例如使用Promises.all(),它会在数组中的所有承诺都被解决时解决。
  • @mepley 您的代码有效。谢谢!现在我明白出了什么问题。
  • 感谢 @KiranMathewMohan 注意到我忘记了 Promise.all() 周围的承诺!
【解决方案2】:

您的代码的问题是您混合了 Promise 概念(async/await 是一种语法糖 - 所以同样的东西)以及回调概念。

return 语句在 parseString() 的 callback() 之外,回调可能会在返回结果后执行,只是因为 parseString() 是一个异步函数。

因此,在下面的解决方案中,我将 parseString() 包装在一个 Promise 中,以便等待它。

const parseStringPromisified = async xmlData => {
  return new Promise((resolve, reject) => {
    parseString(xmlData, (err, json) => {
      if (err) {
        reject(err);
      }
      resolve(json);
    });
  });
};

const getMainData = async val => {
  //get xml data from the API
  const xmlData = await getSiteContent(`value`); //axios call
  const json = await parseStringPromisified(xmlData);
  const { entry } = json.feed; // array of results.
  const result = entry.map(async report => {
    const secondInfo = await getSomeMoreData(report.something); //axios call
    return {
      id: report.id,
      date: report.date,
      title: report.title,
      info: secondInfo
    };
  });
  return Promises.all(result);
};

【讨论】:

  • 当然不用担心。
猜你喜欢
  • 2016-07-05
  • 1970-01-01
  • 2018-03-15
  • 2020-04-19
  • 2016-01-10
  • 1970-01-01
  • 2018-01-21
  • 1970-01-01
  • 2022-01-18
相关资源
最近更新 更多