异步:在回调内部获取空数组

时间:2015-01-10 00:44:53

标签: javascript node.js mongodb express mongoose

我尝试将数据库查询的结果存储在数组中,但我总是得到一个空数组。我不太了解Async是如何工作的,但我认为这段代码应该可行,因为我在完成之前存储了该变量

注意:以下是一个数组也是我理解这个问题是因为异步行为但我不知道该怎么做才能解决它

代码:

    exports.getfollowingUser = function(req, res){
  followedUser=[];
  following = req.user.follow;

  for (i = 0; i < following.length; i++) { 
    User.find(following[i].followed, function (err, followUser){
    followedUser[i]= followUser;
    });
    }
    console.log(followedUser) // result empty
    res.render('following', {
      followedUser: followedUser 
    });
  };

编辑:1 关注架构

module.exports = mongoose.model('Friendship',{

    follower: String,
    followed: String
});

编辑:2 用户架构

module.exports = mongoose.model('User',{

    email:{
        type: String,
        unique: true,
        lowercase: true },

    password:String,

    profile:{
        fullname: String,
        gender: String,
        role: {type: String, default: 'Autorizado'},
        country: String },

});

注意:我正在尝试吸引用户(登录)关注的朋友并在视图中显示他们。

2 个答案:

答案 0 :(得分:0)

查看执行流程:

exports.getfollowingUser = function(req, res){
    followedUser=[];                                                  // 1
    following = req.user.follow;

    for (i = 0; i < following.length; i++) {                          
        User.find(following[i].followed, function (err, followUser){  // 2,3,4
            followedUser[i]= followUser;                              // 7,8,9
        });
    }
    console.log(followedUser) // result empty                         // 5
    res.render('following', {followedUser: followedUser});            // 6
};

如您所见,在console.log [5]时,followedUser[i]= followUser尚未执行[7,8,9]。这就是你获得空数组的原因。

以下是您可以解决的问题

exports.getfollowingUser = function(req, res){
    followedUser=[];                                                  // 1
    following = req.user.follow;

    var counter = 0;
    var length = following.length;

    for (i = 0; i < following.length; i++) {                          
        User.find(following[i].followed, function (err, followUser){  // 2,3,4
            followedUser[i]= followUser;                              // 7,8,9
            counter++;
            if(counter>=length) allDone();                            // 10
        });
    }

    console.log(followedUser) // result empty                         // 5
    res.render('following', {followedUser: followedUser});            // 6        

    function allDone(){
        console.log(followedUser) // result empty                     // 11
        res.render('following', {followedUser: followedUser});        // 12       
    }
};

这里相同的陈述但在allDone() [11,12]内部会做你期望他们做的事情,因为他们在[7,8,9]之后执行。

这只是为了解释,有更好的库来处理这样的事情:

也很有帮助:https://blog.engineyard.com/2015/taming-asynchronous-javascript-with-async

答案 1 :(得分:0)

在for循环node中,只需向您的数据库发出请求并继续处理。它不会等待数据库的结果。这是异步工作的方式。因此,在您的for循环node尚未收到来自数据库的结果后,followedUser为空。要在没有第三方库的情况下解决此问题,您可以执行以下操作:

exports.getfollowingUser = function(req, res){

    findFollowedUser(req.user.follow, function(error, followedUser) {
        console.log(followedUser);
        res.render('following', {
            followedUser: followedUser
        });
    });

    function findFollowedUser(following, callback) {
        var followedUser=[];
        var waiting  = following.length;
        var wasError = false;

        for (var i = 0; i < following.length; i++) {
            User.find(following[i].followed, function (err, followUser){
                if (wasError) {
                    return;
                }

                if (err) {
                    wasError = err;
                    return callback(err);
                }

                followedUser[i]= followUser;
                waiting--;

                if (!waiting) {
                    callback(null, followedUser);
                }
            });
        }
    }
};

另一种方式(我认为更好)是使用一些流控制库。例如:

我的个人偏好:bluebird - 实现极快的承诺。实际上 promises 即将推出的javascript标准。所以我建议你仔细看看它。

另外,我建议您观看this video。这是javascript异步模型的非常简化的解释(事件循环如何工作)。