node.js - 将猫鼬查询结果推送到全局数组
问题描述
我正在尝试使用 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,
});
解决方案
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("/");
}
});
推荐阅读
- api - Facebook Workplace SCIM Api:将有电子邮件的用户转换为无电子邮件用户
- vb.net - 如何使用 printdocument 在水平线上打印 datagridview 数据?
- php - cookie 名称中的无效字符超出了错误消息中列出的内容
- kubernetes - 错误消息 exec.go:282] 从相同的 exec auth 配置构造多个客户端实例可能会在证书轮换期间导致性能问题
- google-cloud-platform - 查找 GCP 存储桶的子目录大小
- python - 是否可以使用可微张量流操作来执行这种转换?
- r - 分离并计算具有多个值的列
- python - 如何在 SQLite 中实现模糊搜索?
- javascript - 从 Facebook InApp 浏览器使用 JS 在设备默认浏览器中打开链接
- python - Maya - 为使用 Python 选择的每个关节创建 ikHandle