首页 > 解决方案 > mongoose.save 的问题永远不会在承诺内返回

问题描述

更新 !!

我在下面的 Dacre Denny 答案的帮助下解决了我最初的问题,但是在为我的代码编写测试时,结果发现在服务器响应之前没有保存更改,因为我的测试数据库中的公司集合是空的,我解决了这个问题以下代码

  Companies.find({ company_name: company.company_name }).then(found => {
    if (found.length !== 0) {
      return res.status(400).json({ error: "Company already exists" });
    }

    var userForms = company.users;
    company.users = [];
    const finalCompany = new Companies(company);
    console.log(finalCompany);

    var userPromises = [];
    for (var x = 0; x < userForms.length; x++) {
      var user = userForms[x].user;
      user.company = finalCompany._id;
      userPromises.push(userCreation(user));
    }
    return Promise.all(userPromises).then(responses => {
      for (var x in responses) {
        if (!responses[x].errors) {
          finalCompany.addUser(responses[x]._id);
        } else {
          res.status(400).json(responses[x]);
        }
      }
      return finalCompany;
    });
  })
  // I moved the save in here !!!
  .then((finalCompany) => {
      finalCompany.save().then(()=>{
        res.status(200).json({signup:"Successful"});
      })
  },(err) => {
      res.json({error: err});
  });
});

原始问题

我正在尝试创建一个代表公司的猫鼬文档,此代码将模型保存在我的数据库中,但是当我提出请求时,它似乎没有响应状态代码或回复邮递员

我已经使用调试器单步执行代码,但我对我的 JS 非常生疏,而且我担心我已经陷入了深水,而我的承诺已经超出了我的想象。

router.post('/c_signup', auth.optional, (req, res, next) => {

  const { body: { company } } = req;

  var error_json = cbc(company);

  if( error_json.errors.length > 0 ){
    return res.status(422).json(error_json);
  }

  Companies.find({company_name: company.company_name})
  .then((found) => {
    if (found.length !== 0) {
      return res.status(400).json({error: "Company already exists"});
    }

    var userForms = company.users;
    company.users = [];
    const finalCompany = new Companies(company);

    var userPromises = [];
    for (var x =0; x < userForms.length; x ++) {
      var user = userForms[x].user;
      user.company = finalCompany._id;
      userPromises.push(userCreation(user));
    }

    Promise.all(userPromises).then((responses) => {
      for (var x in responses){
        if (!responses[x].errors){
          finalCompany.addUser(responses[x]._id);
        }
        else {
          res.status(400).json(responses[x]);
        }
      }
      console.log("h2");
      finalCompany.save(function () {
        console.log("h3");
        return res.status(200);
      });
    })
  });

  return res.status(404);
});

这是调试的输出,但执行在这里挂起

h2
h3

标签: javascriptnode.jsmongoose

解决方案


这里有几个问题:

首先,save()函数是异步的。您需要通过确保save()返回的承诺返回到调用它的处理程序来解决这一问题。

调用也是如此Promise.all()- 您需要通过将该承诺返回给封闭的处理程序来将该承诺添加到相应的承诺链中(参见下面的注释)。

此外,请确保请求处理程序通过res.json()res.send()等返回响应,或者通过简单地调用res.end(). 这表明请求已经完成,应该解决“挂起行为”。

尽管您的代码包含res.json(),但在许多情况下不能保证调用它。在这种情况下,会导致挂起行为。解决此问题的一种方法是添加res.end()到您的承诺链的末尾,如下所示:

Companies.find({ company_name: company.company_name }).then(found => {
  if (found.length !== 0) {
    return res.status(400).json({ error: "Company already exists" });
  }

  var userForms = company.users;
  company.users = [];
  const finalCompany = new Companies(company);

  var userPromises = [];
  for (var x = 0; x < userForms.length; x++) {
    var user = userForms[x].user;
    user.company = finalCompany._id;
    userPromises.push(userCreation(user));
  }

  /* Add return, ensure that the enclosing then() only resolves
after "all promises" here have completed */
  return Promise.all(userPromises).then(responses => {
    for (var x in responses) {
      if (!responses[x].errors) {
        finalCompany.addUser(responses[x]._id);
      } else {
        res.status(400).json(responses[x]);
      }
    }
    console.log("h2");

    /* Add return, ensure that the enclosing then() only resolves
    after the asnyc "save" has completed */
    return finalCompany.save(function() {
      console.log("h3");
      return res.status(200);
    });
  });
})
.then(() => {
    res.end();
},(err) => {
    console.error("Error:",err);
    res.end();
});

推荐阅读