【问题标题】:How to await for async function results in nodejs如何等待异步函数导致nodejs
【发布时间】:2020-01-09 06:20:19
【问题描述】:

我正在编写代码来添加与我的 json 数据中每一行对应的数据。 所有功能和代码编写都已完成。当所有数据都被调用后,它应该返回 json。 但在执行所有代码之前,它会返回 json。 所以即使所有代码都运行良好,json 总是返回一个空值。 请指教。

var request = require('request');
var axios = require('axios');

router.get('/geometric/getAddress', async (req, res) => {
    let confmKey = "secret";
    let resultType = "json";
    let countPerPage = "10"

    let page = appjs.vCheck(req.query.page, "");
    let kw = appjs.vCheck(req.query.keyword, "");

    var stmt = "http://10.10.100.12:8080/addr.do?";
    stmt = stmt + "currentPage=" + page; 
    stmt = stmt + "&countPerPage=" + countPerPage;
    stmt = stmt + "&resultType=" + resultType;
    stmt = stmt + "&confmKey=" + confmKey;
    stmt = stmt + "&keyword=" + qs.escape(kw)

    request(stmt, async (err, result) => {
        if (err) throw err;

        const con = JSON.parse(result.body);
        const juso = con.results.juso;


        var dd = ""
        let res_data = juso.map(async (addr) => {
            let admCd = appjs.vCheck(addr.admCd, "");
            let rnMgtSn = appjs.vCheck(addr.rnMgtSn, "");
            let udrtYn = appjs.vCheck(addr.udrtYn, "");
            let buldMnnm = appjs.vCheck(addr.buldMnnm, "");
            let buldSlno = appjs.vCheck(addr.buldSlno, "");

            axios.post("http://localhost:3001/web/api/geometric/coordinates",
                {
                    admCd : admCd,
                    rnMgtSn : rnMgtSn,
                    udrtYn : udrtYn,
                    buldMnnm : buldMnnm,
                    buldSlno : buldSlno
            }).then((d) => {
                return {
                    "roadAddr" : d.roadAddr,
                    "jibunAddr" : roadAddr,
                    "zipNo" : d.roadAddr,
                    "longitude" : roadAddr,
                    "latitude" : d.roadAddr
                }
            })
        })

        let aa = await Promise.all(res_data)
        res.json(aa)
    })
});

【问题讨论】:

  • 你不会从map回调中返回承诺。
  • 你为什么要混合axiosrequest 来处理你的http 请求?一个返回一个承诺,另一个没有。

标签: javascript node.js promise es6-promise


【解决方案1】:

发生这种情况是因为您没有从 map 回调中返回任何承诺。你应该这样做:

let res_data = juso.map(async (addr) => {
  let admCd = appjs.vCheck(addr.admCd, "");
  let rnMgtSn = appjs.vCheck(addr.rnMgtSn, "");
  let udrtYn = appjs.vCheck(addr.udrtYn, "");
  let buldMnnm = appjs.vCheck(addr.buldMnnm, "");
  let buldSlno = appjs.vCheck(addr.buldSlno, "");

  return axios.post("http://localhost:3001/web/api/geometric/coordinates",
    {
      admCd : admCd,
      rnMgtSn : rnMgtSn,
      udrtYn : udrtYn,
      buldMnnm : buldMnnm,
      buldSlno : buldSlno
     })
   })

let aa = (await Promise.all(res_data)).map(({data: d}) => ({
  "roadAddr" : d.roadAddr,
  "jibunAddr" : roadAddr,
  "zipNo" : d.roadAddr,
  "longitude" : roadAddr,
  "latitude" : d.roadAddr
}));

res.json(aa)

【讨论】:

    【解决方案2】:

    由于您没有从map 函数返回任何promise,因此await Promise.all(res_data) 是微不足道的代码。

    更新:

    • Axios 库返回完整的 Promise,因此可以简单地从地图回调中返回。
    • 然后可以等待这些返回的 Promise 并将其映射到所需的结果。
      let res_data = juso.map(async addr => {
      let admCd = appjs.vCheck(addr.admCd, "");
      let rnMgtSn = appjs.vCheck(addr.rnMgtSn, "");
      let udrtYn = appjs.vCheck(addr.udrtYn, "");
      let buldMnnm = appjs.vCheck(addr.buldMnnm, "");
      let buldSlno = appjs.vCheck(addr.buldSlno, "");
    
      return axios.post("http://localhost:3001/web/api/geometric/coordinates", {
        admCd: admCd,
        rnMgtSn: rnMgtSn,
        udrtYn: udrtYn,
        buldMnnm: buldMnnm,
        buldSlno: buldSlno
      });
    });
    

    然后await 用于返回的承诺(try/catch 用于任何失败的承诺或Promise.all(res_data).then().catch(e) 也用于处理错误):

    await Promise.all(res_data)
      .then(resolvedPromises => {
        const aa = resolvedPromises.map(d => ({
          roadAddr: d.roadAddr,
          jibunAddr: d.roadAddr,
          zipNo: d.roadAddr,
          longitude: d.roadAddr,
          latitude: d.roadAddr
        }));
    
        return res.json(aa);
      })
      .catch(e => {
        //handle error because one of those axios promises failed: e.message
      });
    

    【讨论】:

    • @Bergi 我知道axios 确实返回了promise,并且将promise 包装在promise 中是不好的,并且返回它会更简单。尽管代码的编写方式可能不在这种情况下。这里 catch(e) 处理程序与 reject 在 axios 确实会冒泡错误作为拒绝 Promise.all。我错过了什么?
    • 是的,只是返回承诺会简单得多,并且工作方式相同。不确定您所说的拒绝冒泡是什么意思,您认为反模式代码的工作方式有何不同?
    • 是的,你没有忘记捕获内部错误并拒绝外部承诺,所以这很好,但它仍然是应该简化的完全过于复杂的代码。即使正确实现,promise 构造函数反模式仍然会导致非常容易出错的代码。
    • 我建议您 edit 您自己的答案以删除承诺反模式 - 答案的其余部分,尤其是解释,仍然很好 - 并且您支持您提出的所有其他答案认为是好的。
    猜你喜欢
    • 2020-09-23
    • 2018-05-27
    • 2020-06-03
    • 1970-01-01
    • 2021-08-27
    • 1970-01-01
    • 2018-09-29
    • 1970-01-01
    相关资源
    最近更新 更多