首页 > 解决方案 > 将猫鼬查询结果推送到全局数组

问题描述

我正在尝试使用 mongoose 来查询我的 mongodb 集合,但没有呈现结果。我想我知道为什么,因为某事,某事,异步/等待/承诺,但没有任何效果。基本上我想要 2 个查询,一个是拉取在请求的链接 (workflowID) 中记录的对象,它本身有几个“步骤”,这些“步骤”在对象 ID 的数组中被引用。它们没有被推送到作用域变量(workflowStepCombined)。查询按预期工作,如果我在 forEach 中记录结果,我会得到我所期望的结果。就像我提到的那样,我认为问题在于应用程序没有等待结果,我已经多次阅读了有关承诺的猫鼬文档并实施了我认为的解决方案,但是在重构一整天后没有任何进展。

app.get("/new/:workflowID", function (req, res) {
  if (req.isAuthenticated()) {
    const workflowID = req.params.workflowID;
    //define array to push recombined steps to
    let workflowStepCombined = [];
    Workflow.findOne({ workflowName: workflowID }, function (err,foundWorkflow) {
        const stepsArray = foundWorkflow.workflowStepArray;
        //once workflow found, start pulling from step collection the listed IDs
        stepsArray.forEach(function (step) {
          Steps.findOne({ _id: step }, (err, foundStep) => {
              //push to array that was definedin first part
              workflowStepCombined.push(foundStep);
          });
        });
        //render it all together
        res.render("contracts/" + workflowID, {
          userID: req.user.username,
          workflow: workflowStepCombined,
        });
      }); 
    } else {
        res.redirect("/");
        }
    });

我也尝试使用 .then ,因为根据我有限的理解,我需要让它等待查询结果,然后再转到下一行代码。但这也不起作用,它的行为相同。

app.get("/new/:workflowID", function (req, res) {
  if (req.isAuthenticated()) {
      //allows for dynamic link creation
    const workflowID = req.params.workflowID;
    const stepsArray = [];
    //define array to push recombined steps to
    let workflowStepCombined = [];

    //find workflow with name from link
    Workflow.findOne({ workflowName: workflowID }).then(foundWorkflow => {
      stepsArray.push(foundWorkflow.workflowStepArray);
    })
    console.log(stepsArray)
    //once workflow found, start pulling from step collection the listed IDs
    stepsArray.forEach(function (step) {
    Steps.findOne({ _id: step }).then(foundStep => {
        workflowStepCombined.push(foundStep);
        console.log(foundStep);
     });
    });
      //render it all together
      res.render("contracts/" + workflowID, {
        userID: req.user.username,
        workflow: workflowStepCombined,
      });

标签: node.jsmongodbmongoose

解决方案


forEach 函数不是异步的,因此在获取步骤结果之前调用 res.render。你应该使用 Promise.all 函数

Promise.all(stepsArray.map(step => Steps.findOne({ _id: step })))
  .then(workflowStepCombined => {
    return  res.render("contracts/" + workflowID, {
      userID: req.user.username,
      workflow: workflowStepCombined,
    });
  })

我建议你使用 async/await 方法而不是回调

app.get("/new/:workflowID", async (req, res) => {
  if (req.isAuthenticated()) {
    const workflowID = req.params.workflowID;
    //define array to push recombined steps to
    let workflowStepCombined = [];
    const workflow = await Workflow.findOne({ workflowName: workflowID });
    const stepsArray = foundWorkflow.workflowStepArray;
    const workflowSteps = await Steps.find({_id: {$in: stepsArray}}) //https://docs.mongodb.com/manual/reference/operator/query/in/ and you could use sort here if needed - https://mongoosejs.com/docs/api.html#model_Model.find

    //render it all together
    res.render("contracts/" + workflowID, {
      userID: req.user.username,
      workflow: workflowSteps,
    });
  } else {
    res.redirect("/");
  }
});

推荐阅读