繁体   English   中英

在NodeJS MongoDB中的嵌套for循环和回调中保留执行顺序

[英]Preserving Execution order in nested for loop and callbacks in NodeJS MongoDB

Scenario: There are users and users has many posts. For a particular group of users, I need to fetch 10 recent posts per user and send them in response.
Here is what I have come up with:

users是具有用户信息的数组。

var allPosts = [];

for(var i=0; i<users.length; i++){
    (function(i){                                               //Level-1 
        db.collection('posts', function(err, postCollection){
            (function(i){                                       //Level-2
                postCollection.find({"user_id": users[i]['user_id']}).sort({"created": -1}).limit(10).toArray(function(err, post) {
                    (function(i){                               //Level-3
                        for(var j =0; j< post.length; j++){
                            (function(j){
                                post[j]['created'] = ObjectId(post[j]['_id'].toString()).getTimestamp();
                                allPosts.push(post[j]);
                                if(j === post.length-1){
                                    res.send(allPosts);
                                }
                            })(j);
                        }    
                    })(i);
                });
            })(i);
        });    
    })(i);                        
}

现在,执行顺序一直保留到Level-2,但是当它进入Level-3时,一切都出错了:我在阵列中有两个用户,一个用户有3个帖子,另一个用户有10个帖子,有时响应只有3个帖子,有时是全部13个帖子。 我认为这是因为MongoDB。 我什至通过使用立即调用的函数expression(IIFE)来照顾执行顺序,但在这里似乎不起作用。 任何帮助表示赞赏。 谢谢

首先,您应该美化您的代码。 在其他循环的回调内部的循环内部使用匿名函数并不容易维护或读取。

您的代码的问题在于,在最后一个循环(j循环)中,在完成对其他用户的查询之前,您进入j == users.length-1,因此,发送该请求之前的查询数量已完成。

您犯的另一个大错误是您在一个循环中请求了post集合。 错了! 您应该同时缓存数据库和集合。

试试这个代码:

var allPosts = [];
var post_collection = null;

var get_user = function(i, callback) {
    post_collection
        .find({"user_id": users[i]['user_id']})
        .sort({"created": -1})
        .limit(10)
        .toArray(function(err, post) {

            // Do something when you get error
            // Always call the callback function if there is one
            if(err) {
                callback();
                return;
            }

            for(var j=0; j<post.length; ++j) {
                post[j]['created'] = ObjectId(post[j]['_id'].toString()).getTimestamp();
                allPosts.push(post[j]);
            }

            callback();
        });
};

var fetch_users = function() {
    var count = users.length;

    for(var i=0; i<users.length; ++i) {
        get_user(i, function() {
            // Each time a query for one user is done we decrement the counter
            count--;

            // When the counter is 0 we know that all queries have been done
            if(count === 0) {
                res.send(allPosts);
            }
        });
    };    
};

// Get the collection, check for errors and then cache it!
db.collection('posts', function(err, postCollection) {

    // Always check for database errors
    if(err) {
        console.log(err);
        return;
    }

    post_collection = postCollection;
    fetch_users();
});

您应该知道此代码未经测试。 我可能错过了分号或花括号,但您应该轻松弄清楚。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM