异步:在回调中获取 For 之后的空数组



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

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

法典:

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

注意:我正在尝试获取用户(登录)正在关注的好友,并在视图中显示它们。

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

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

  • 蓝 鸟
  • 异步
  • 纤维

我个人的喜好:蓝鸟 - 极快的承诺实现。实际上,承诺是即将到来的JavaScript标准。所以我建议你仔细看看它。

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

看看执行流程:

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://github.com/caolan/async#each
  • 承诺:https://gist.github.com/neilk/8467412

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

最新更新