我已经阅读了几篇关于此的帖子和文章,但我无法理解。
我的Mongoose模型中有一段代码,主要负责邀请人们参与项目。鉴于一些受邀者,我希望看看他们是否在数据库中,如果不是,我继续创建它们并更新被邀请者列表中的ID。
jslint抱怨循环并且我正在努力应对回调(当你有一个带有回调的数据库保存的循环时,正确的整体模式。显然我想要发生的是循环完全完成,任何新用户被添加到数据库中,ids是原始哈希(被邀请者)中的更新,然后回调发生。
ProjectSchema.methods.invite = function invite(invitees, callback) {
var User = mongoose.model('User');
var emails = _.pluck(invitees, 'email');
// loop through invited hash to see if we already have those users in the db
User.find({ 'email': { $in: emails}}, function (err, users) {
for (var invited = 0; invited < invitees.length; invited++) {
var found = false;
// logic here to see if they are already users using the users param
if (found) {
// they are already in the db so do unrelated things.
} else {
// create new user
var User = mongoose.model('User');
var newUser = // set up new user here
newUser.save(somecallback?);
// update invitees list with id
}
}
callback(err, invitees);
});
};
答案 0 :(得分:1)
这里有几个问题:
您在for循环中声明局部变量。这是不鼓励的,因为JavaScript具有功能范围,而不是块范围(可变提升)。
您需要某种方法来同步为保存到数据库的每个用户所做的异步更改,即“等待”循环完成。
对于1.,我建议你使用Array.map
,即声明一个函数
function processUser (invited) {
// essentially the body of your for loop
}
然后拨打invitees.map(processUser)
。
2.问题更难:我建议您使用提供异步支持的库,例如Q。
为此,让processUser
函数返回已完成时已解析的Q promise,然后使用Q.all
进行同步。就像这样:
Q.all(invitees.map(processUser))
.then(function (completions) {callback(null,invitees);},
function (err) {callback(err,null);});
结束:
// import Q
var Q = require('q');
// ...
ProjectSchema.methods.invite = function invite(invitees, callback) {
var User = mongoose.model('User');
var emails = _.pluck(invitees, 'email');
// loop through invited hash to see if we already have those users in the db
function processUser (invited) {
var deferredCompletion = Q.defer();
var found = false;
// logic here to see if they are already users using the users param
if (found) {
// they are already in the db so do unrelated things.
// ...
deferredCompletion.resolve(true); // resolve with some dummy value
} else {
// create new user
var newUser = // set up new user here
newUser.save(function (err, user){
if (err) {
deferredCompletion.reject(err);
} else {
// update invitees list with id
// ...
deferredCompletion.resolve(true);
}
});
}
return deferredCompletion.promise;
}
Q.all(invitees.map(processUser))
.then(function (completions) {
callback(null,invitees);
}, function (err) {
callback(err,null);
});
};