在内部forEach循环中集成异步mongo调用

Integrating asynchronous mongo call within an inner forEach loop

本文关键字:异步 mongo 调用 集成 forEach 循环 在内部      更新时间:2023-09-26

我得到了两个循环,外部循环遍历用户,内部循环遍历每个用户的venueID。在内部循环中,我想查找场地并将其附加到外部外观(userItem)中定义的数组。然而,由于forEach是同步的,而mongo数据库查询是异步的,所以结果总是为空。我试着把这个答案整合起来,但无济于事。如何做到这一点?

ret = [];
users.forEach(function(user) {
    var userItem = user.getSanitised('ADM');
    userItem.venues = [];
    var tmp = [];
    userItem.adminVenueIds.forEach(function(adminVenueId){
        tmp.push(function(callback) {
            Venue.findOne({_id:adminVenueId}, function(error, venue) {
                callback(null, venue.toObject());
            });
        });
    });
    async.parallel(userItem.venues, function(err, result) {
        /* this code will run after all calls finished the job or
         when any of the calls passes an error */
        if (err)
            return console.log(err);
        userItem.venues.push(result);
    });
    ret.push(userItem);
});

也尝试了以下操作,但也不成功

users.forEach(function(user) {
    var userItem = [];
    async.series({
            setUserItem : function(callback)
            {
                userItem = user.getSanitised('ADM');
                callback(null, 'OK');
            },
            setUserVenues : function(callback)
            {
                userItem.venues = [];
                user.adminVenueIds.forEach(function(adminVenueId,index) {
                    Venue.findOne({_id:adminVenueId}, function(error, venue) {
                        userItem.venues.push(venue.toObject());
                        if((index+1) == user.adminVenueIds.length)
                            callback(null, 'OK');
                    });
                });
            }
        },
        function(error, results) {
            if(error)
                winston.error(error);
            ret.push(userItem);
        }
    );

});

你可以简单地输入一个if语句(在你的例子中,将条件作为数组长度),然后当循环完成后,你可以通过调用一个函数来继续(或者把你的代码放在那里,但它会开始看起来很乱),让它继续做它的事情

var ret = [];
var test = [];

for (var i = 0; i < 20; i++) {
    for (var x = 0; x < 20; x++) {
         setTimeout(function() {
            test.push("Test"+x);
            if (x === 20) {
                finishIt();
            }
        }, 300)
    }
}

function finishIt() {
    console.log(test);
    ret.push(test);
}

我想你可能想看看使用Mongoose。它是MongoDB之上的NodeJS应用层,提供了更像SQL的体验。

http://mongoosejs.com

我最终得到了以下解决方案。这很脏,但我想nodejs就是nodejs。

users.forEach(function(user) {
    var userItem = user.getSanitised('ADM');
    userItem.venues = [];

    user.adminVenueIds.forEach(function(adminVenueId) {
        Venue.findOne({_id:adminVenueId}, function(error, venue) {
            userItem.venues.push(venue.toObject());
        });
    });
    (function(){
        if(userItem.venues.length == user.adminVenueIds.length) {
            ret.push(userItem);
        } else {
            setTimeout(arguments.callee, 30);
        }
    })();
});