节点Js异步等待给出第一个响应为空

时间:2019-01-18 12:04:18

标签: node.js async-await

我是节点js中异步/等待编码的新手。我试图从mongodb获取数据,然后将结果填充到一个对象中。但是,当我退出服务器并重新打开服务器,然后在节点js中访问API时,我面临一个奇怪的问题,第一个响应始终为空。在第一次尝试以下是我的代码后,我一点击API就开始获得响应

let resu={};

router.get('/getTarrifDetails',async (req,res,next) => {
  await Tarrif.find().distinct('tarrif_type',(err,docs) => {
    docs.forEach(async (ele) => {
      let count= User.countDocuments({tarrif_type:ele});
      result.push(ele);
      result[ele] = await count;
      result.push(count);
    });
  });

  getAll(res);
});

async function getAll(res) {
  if(await resu.length!=0) {
    res.send(resu);
  }
}

2 个答案:

答案 0 :(得分:1)

您需要先确定 await 语句已完成,然后才能进行比较。 请记住, async / await 不会使代码同步运行,它只是以一种使我们的开发人员看起来像同步的方式对其进行格式化。

function findData() {
      return Tarrif.find().distinct('tarrif_type',(err,docs)=>{
          docs.forEach(async (ele)=>{
          let count= User.countDocuments({tarrif_type:ele});
          result.push(ele);
          resu[ele]=await count;
          result.push(count);
        });
      });
    };


router.get('/getTarrifDetails',async (req,res,next)=>{
    let res = null;
    try {
       res = await findData();
    } catch(e) {
      console.log(e);
    }
    if(res !== 0){
      //do something
    } else {
      // do something else
    }

});

答案 1 :(得分:1)

您的代码错误。

1)不建议将上下文变量resu存储在请求范围之外。

2)result.pushresult变量在哪里?再次超出范围?

3)resu.length?它不是一个数组,而是一个对象,因此不会得到false0的结果。

4)find().distinct('tarrif_type', (err,docs) => ...猫鼬支持诺言,那么为什么要在回调中使用它呢?

5)await resu.length?这不是一个承诺,它只是一个对象,而长度是属性,您不能从非承诺属性中询问await

6)getAll如果resu.length确实会有0怎么办?它会如何回应? -因此请求将挂起,因此您必须做出任何响应才能正常关闭请求期间创建的连接。


因此整体修复应该有效:

router.get('/getTarrifDetails', async (req, res) => {
  try {
    const tarrifTypes = await Tarrif.find().distinct('tarrif_type');

    const tarrifCounters = {};
    let total = 0;
    for(const tarrifType of tarrifTypes) {
      const count = await User.count({tarrif_type: tarrifType});
      tarrifCounters[tarrifType] = count;
      total+= count;
    }

    res.status(200).send({
      tarrifTypes,
      tarrifCounters,
      total
    });
  } catch(error) {
    res.status(500).send(error.message);
  }
});

或使用并行性:

const getTarrifUsersCounters = async (tarrifTypes) => {
  // initial result
  const result = {
    tarrifTypes,
    tarrifCounters: {},
    total: 0
  };

  // if no tarriffTypes passed return result
  if (!(Array.isArray(tarrifTypes) && tarrifTypes.length > 0)) {
   return result;
  }

  // generating array of promises from tarrifTypes
  const callStack = [];
  for(const tarrifType of tarrifTypes) {
    callStack.push(
      new Promise(async resolve => {
        const count = await User.count({tarrif_type: tarrifType});
        resolve({tarrifType, count});
      });
    );
  }

  // calling promises array in parallel
  if (callStack.length) {
    (await Promise.all(callStack))
      .forEach(
        ({tarrifType, count}) => {
          result.tarrifCounters[tarrifType] = count;
          result.total += count;
        });
  }

  return result;
};

router.get('/getTarrifDetails', async (req, res) => {
  try {
    const tarrifTypes = await Tarrif.find().distinct('tarrif_type');
    const result = await getTarrifUsersCounters(tarrifTypes);
    res.status(200).send(result);
  } 
  catch(error) {
    res.status(500).send(error.message);
  }
});