我正在使用for循环来创建和保存多个文档,然后将其ID推入对另一个文档的引用,稍后我将尝试保存。
但是,当我执行代码时,最终文档保存发生在for循环之前,这意味着引用永远都不会保存。
如何在保存另一个文档(在我的情况下为条目)之前完成for循环?还是有一种完全不同的更好的方式来完成我要完成的工作?
我尝试将代码分成两个异步等待函数,还尝试将代码分为一个带有回调的函数,该回调在完成后会调用另一个函数。我目前正在尝试更深入地理解Promises。我还在探索是否可以设置标志或稍稍延迟时间。
Template.findById(templateId, function (err, template) {
if (err) { return console.log(err) }
let entry = new Entry();
entry.entryState = "Draft";
entry.linkedTemplateId = template._id;
for (var i = 0; i < template.components.length; i++) {
let component = template.components[i]
let entryComp = new entryComponent({
componentOrder: component.componentOrder,
componentType: component.componentType,
templateComponentId: component._id,
entryId: entry._id
})
entryComp.save(function(err){
if (err) { return console.log(err) }
entry.entryComponents.push(entryComp._id);
});
}
entry.save(function(err){
if (err) { return console.log(err) }
});
})
答案 0 :(得分:1)
我喜欢为此目的使用递归。尽管我非常确信别人已经在我之前想到了这一点,但是我还是自己发现了这种解决方案。由于我是自己解决这个问题的,因此我不确定这是否是最好的处理方法。但是我已经使用了它,并且它在我的应用程序中很好地工作。
Template.findById(templateId, function (err, template) {
if (err) { return console.log(err) }
let entry = new Entry();
entry.entryState = "Draft";
entry.linkedTemplateId = template._id;
var fsm = function(i){
if (i<template.components.length)
{
let component = template.components[i]
let entryComp = new entryComponent({
componentOrder: component.componentOrder,
componentType: component.componentType,
templateComponentId: component._id,
entryId: entry._id
})
entryComp.save(function(err){
if (err) { return console.log(err) }
entry.entryComponents.push(entryComp._id);
//cause the fsm state change when done saving component
fsm(i+1)
});
}
else
{
//the last index i=length-1 has been exhausted, and now i= length, so
//so do not save a component, instead save the final entry
entry.save(function(err){
if (err) { return console.log(err) }
});
}
}
//start the fsm
fsm(0)
})
简而言之,我将使用递归来解决问题。但是,如果组件的数组很大,则可能会超出递归堆栈限制。考虑限制此应用程序中允许的项目数量。
答案 1 :(得分:1)
您可以在javascript中使用新的“ for of”循环以及异步等待来简化答案:-
Template.findById(templateId, async function (err, template) {
try {
if (err) { return console.log(err) }
let entry = new Entry();
entry.entryState = "Draft";
entry.linkedTemplateId = template._id;
for(const component of template.components) {
let entryComp = new entryComponent({
componentOrder: component.componentOrder,
componentType: component.componentType,
templateComponentId: component._id,
entryId: entry._id
})
await entryComp.save();
entry.entryComponents.push(entryComp._id);
}
await entry.save();
} catch (error) {
// handle error
}
})
另一种方法是通过Promise.all使用常规的“ for循环”,这将比另一种更快,因为您无需再等待一个entryComp的保存就可以了:-
Template.findById(templateId, async function (err, template) {
try {
if (err) { return console.log(err) }
let entry = new Entry();
entry.entryState = "Draft";
entry.linkedTemplateId = template._id;
const promises = [];
for (var i = 0; i < template.components.length; i++) {
let component = template.components[i]
let entryComp = new entryComponent({
componentOrder: component.componentOrder,
componentType: component.componentType,
templateComponentId: component._id,
entryId: entry._id
})
promises.push(entryComp.save());
entry.entryComponents.push(entryComp._id);
}
await Promise.all(promises);
await entry.save();
} catch (error) {
// handle error
}
})
此外,如果您要执行相互依赖的多文档操作,则执行这些操作的正确方法是通过mongodb事务处理,这将提供原子性。在这里https://docs.mongodb.com/master/core/transactions/
看看