我今天正在为一个关于流动民主的项目的循环函数而苦苦挣扎。在委派投票时,我有一个循环来检查没有忘记任何代表团,这个算法有一个有趣的行为:
Vote.count({
propId: propId,
delegation: true
}, function(err, voteNumber) {
var maxDelegation = voteNumber;
for (var d = 1; d < maxDelegation + 1; d++) {
var delegationsLeft = 1; //Is calculated to see if someone delegates to a delegate
while (delegationsLeft > 0) {
console.log("I am about to find the votes for " + d + " weight, " + delegationsLeft + " delegation left at least.");
Vote.find({
propId: propId,
delegation: true,
weight: d
}, function(err, specWeightVotes) {
console.log("I'm in.");
delegationsLeft = specWeightVotes.length;
for (var i = 0; i < specWeightVotes.length; i++) {
// Add the weight d, aka the weight of a vote to the delegated voter
Vote.findOneAndUpdate({
propId: propId,
voter: specWeightVotes[i].content
}, {
$inc: {
'weight': specWeightVotes[i].weight
}
}, function(err) {
if (err) {
console.log("Ca bug.");
}
//Put weight as zero for the ones who have delegated
Vote.findOneAndUpdate({
_id: specWeightVotes[i]._id
}, {
$set: {
'weight': 0
}
}, function(err) {
if (err) {
console.log("Ca bug 2.");
}
});
});
}
});
}
}
console.log("I have delegated all votes");
});
现在有趣的是,我的while循环永远停留,因为它永远不会执行代码的Vote.find({propId: propId, delegation: true, weight: d}, function(err, specWeightVotes){
部分。
如果我查看控制台,我有以下输出:
I am about to find the votes for 1 weight, 1 delegation left at least.
I am about to find the votes for 1 weight, 1 delegation left at least.
I am about to find the votes for 1 weight, 1 delegation left at least.
I am about to find the votes for 1 weight, 1 delegation left at least.
I am about to find the votes for 1 weight, 1 delegation left at least.
...直到最后这个过程耗尽电池。我永远不会看到“我在”的一部分。
我想这可以通过一些更多的异步编程来解决吗?但是,考虑到我的功能甚至没有执行一次,我不确定。
PS:重要提示,在包含此while循环以防止委托被遗忘之前,该算法正在运行。
答案 0 :(得分:1)
据推测,Vote.find
的工作异步(对于Vote.findOneAndUpdate
也是如此)。您的for
和while
循环没有。所以delegationsLeft
在循环过程中永远不会是1。
如果您要与异步结果进行互动,则无法使用while
(或for
或do-while
)。相反,您需要在异步回调中安排“循环”的下一次“迭代”。
(或者将所有代码放入ES2017 + async
函数中,将Vote.find
包装在返回Promises的包装器中,并使用await
。但这需要一个尖端的JavaScript要运行的环境,或使用Babel之类的内容进行转换。)