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

时间:2015-06-04 01:52:12

标签: javascript node.js asynchronous

我有两个循环,用户外部循环,内部循环遍历每个用户的venueID。在内部循环中,我想查找场地并将其附加到外部外观(userItem)中定义的数组中。但是因为forEach是同步的并且mongo数据库查找是异步的,所以结果始终为空。我试图整合this answer,但无济于事。怎么做?

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);

        }

    );


});

3 个答案:

答案 0 :(得分:1)

你可以简单地放一个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);
}

答案 1 :(得分:0)

我想你可能想看看使用Mongoose。它是MongoDB之上的NodeJS应用程序层,提供更多类似SQL的体验。

http://mongoosejs.com

答案 2 :(得分:0)

我最终得到了以下解决方案。它很脏,但我想这只是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);
        }
    })();
});