首页 > 解决方案 > 如何在保存另一个文档之前等待循环完成?

问题描述

问题

我正在使用 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) }
        });
    })

标签: javascriptnode.jsmongodbmongoose

解决方案


我喜欢为此目的使用递归。尽管我非常确信其他人在我之前已经想到了这一点,但我确实自己发现了这个解决方案。由于我自己解决了这个问题,我不确定这是否是最好的做事方式。但我已经使用了它,它在我的应用程序中运行良好。

   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)

})

简而言之,我会使用递归来解决问题。但是,如果组件数组非常大,则可能会超出递归堆栈限制。考虑限制此应用程序中允许的项目数量。


推荐阅读