javascript - 如何在保存另一个文档之前等待循环完成?
问题描述
问题
我正在使用 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) }
});
})
解决方案
我喜欢为此目的使用递归。尽管我非常确信其他人在我之前已经想到了这一点,但我确实自己发现了这个解决方案。由于我自己解决了这个问题,我不确定这是否是最好的做事方式。但我已经使用了它,它在我的应用程序中运行良好。
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)
})
简而言之,我会使用递归来解决问题。但是,如果组件数组非常大,则可能会超出递归堆栈限制。考虑限制此应用程序中允许的项目数量。