【问题标题】:NodeJS / Express Why am I getting "Cannot Read Property 'then' of Undefined"?NodeJS / Express 为什么我得到“无法读取未定义的属性'then'”?
【发布时间】:2020-10-12 15:09:38
【问题描述】:

我提前道歉,因为我看到了关于这个主题的其他问题,但我不明白我做错了什么以及如何解决它。请看我的代码:

function getSum(productID) {
  Rating.aggregate(
    [
      {
        $group: {
          _id: "$productID",
          total: {
            $sum: "$rating"
          }
        }
      }
    ],
    function (err, result) {
      if (err) {
        res.send(err);
      } else {
        //console.log("product-sum: " + req.body.productID)
        const count = result.find(item => item._id === productID.productID);
        console.log("getSum count: ", count.total);
        return count.total;
      }
    }
  );
}

router.route('/compute-rating').post((req, res) => {
  console.log("compute Rating: ", req.body.data);
  var productID = req.body.data;
  var sum = getSum(productID).then( //getting the error here

    res.json({ sum })
  );
});

getSum() 从 count.total 中返回一个有效数字。

得到总和后,我计划将另一个 .then 链接到现有 then 并使用 productID 调用另一个函数,但我需要稍后在计算机评分路线中使用总和。

在代码中,我有一条注释显示错误“无法读取未定义的属性'then'”发生的位置。为什么会出现此错误,我该如何解决?

谢谢。

编辑: 我想展示我的最终解决方案,以便其他人可以从我的经验中受益。希望我没有在我的代码中创建任何重大的 Javascript 违规行为。我最终使用了 Promise.all,因为我必须根据 2 个返回值执行计算。

function getSum(productID) {
  return new Promise(async (resolve, reject) => {
    const result = await Rating.aggregate( //sum of a column in MongoDB
      [
        {
          $group: {
            _id: "$productID",
            total: {
              $sum: "$rating"
            }
          }
        }
      ]
    );
    
    try {
      var sum = result.find(item => item._id === productID.productID);

      if (sum !== undefined) {
        resolve(sum);
        console.log("getSum sum: ", sum);
      }
      else {
        reject("invalid product id");
      }

    }
    catch (e) {
      reject(e);
    }
  });
}

function getCount(productID) {
  return new Promise(async (resolve, reject) => {
    
    var result = await Rating.countDocuments(productID)
      .then(count => {
        console.log("getCount count:", result);
        var documentCount = { count: count }
        resolve(documentCount);
      })
      .catch(err => reject(err));
  });
}

router.route('/compute-rating').post((req, res) => {
  console.log("compute Rating: ", req.body.data);
  var productID = req.body.data;

  Promise.all([getSum(productID), getCount(productID)])
    .then(results => {
      console.log("compute rating results: ", results);

      if (results[1].count > 0) {

        res.status(200).json({ rating: results[0].total / results[1].count });
      }
      else {
        res.status(200).json({ rating: 0 });
      }
    })
    .catch(err => {
      res.status(400).json({ error: err });
    })

});

【问题讨论】:

    标签: node.js express promise


    【解决方案1】:

    then 仅适用于返回 promise 的函数。你的函数getSum 没有返回任何东西,如果Rating.aggregate 函数返回一个promise,也就是接受then,那么你应该返回这个聚合,只需在调用它之前添加return

    现在如果aggregate 没有返回一个promise,我猜是因为你向它传递了一个回调函数,你可能想要在这个回调主体中返回一个使用promise.resolve 解析的promise。

    【讨论】:

    【解决方案2】:

    您的getSum 不会返回任何内容。您仅从回调函数返回,而不是 getSum 函数。 你应该把它设为async

    而且您还在该函数中执行res.send,而无法访问res 对象。

    例如你可以这样做:

    async function getSum(productID) {
      const result = await Rating.aggregate(
        [
          {
            $group: {
              _id: "$productID",
              total: {
                $sum: "$rating"
              }
            }
          }
        ]
      );
      const count = result.find(item => item._id === productID.productID);
      console.log("getSum count: ", count.total);
      return count.total;
    }
    
    router.route('/compute-rating').post((req, res) => {
      console.log("compute Rating: ", req.body.data);
      var productID = req.body.data;
      
      // EDIT: This should work
      getSum(productID).then(sum => {
        res.json({ sum })
      });
    });
    

    【讨论】:

    • 使其异步是一个好的开始,但是您没有使用await,这意味着调用then 将是立即的,而不是等待聚合完成,但您又不能await 一个不返回承诺的函数
    • 我在const result = await Rating.aggregate 位中使用await。第一次发的时候忘记了
    • 谢谢...试过你的答案。它摆脱了错误,但我得到了一个空对象。也许我仍然做错了什么......没有正确调用 getSum 。我是一名 C# .Net 开发人员,正在尝试学习 Javascript/Node/React/Mongo/Express。 C# .Net 就简单多了……哈哈
    • console.log in getSum 函数是否打印正确的值?
    • 谢谢。您的编辑就是答案。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-02
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 2017-04-21
    相关资源
    最近更新 更多