我尝试将数据库查询的结果存储在数组中,但我总是得到一个空数组。我不太了解异步的工作原理,但我认为这段代码应该可以工作,因为我在它完成之前存储了变量
注意:下面也是一个数组,我知道这个问题是因为异步行为,但我不知道该怎么做才能解决它
法典:
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