兑现所有承诺后,返回价值

时间:2019-05-14 03:43:46

标签: node.js promise async-await

我正在研究一个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调用的函数。

2 个答案:

答案 0 :(得分: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 };
}

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

答案 1 :(得分:1)

您的代码存在的问题是您将混合诺言概念(异步/等待是一种语法糖-同样)与回调概念一起使用。

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