这段代码有两个问题。
1)仅BeerObjects的最后一个元素保存到数据库中。
2)保存到数据库中的最后一个元素(n = beerObjects.length)有n个重复项。
function addBeersToDatabase(beerObjects) {
for (i = 0; i < beerObjects.length; i++) {
console.log(beerObjects[i].beerId);
var currentBeer = beerObjects[i];
// check if beer is already in database
Beer.findOne({'beerId': currentBeer.beerId}, function(err, beer){
if (err) {
handleError(err);
}
if (beer) {
// beer is already in database
}
else {
// add new beer to database
console.log(currentBeer.beerId);
var newBeer = new Beer();
newBeer.beerId = currentBeer.beerId;
newBeer.name = currentBeer.name;
newBeer.description = currentBeer.description;
newBeer.abv = currentBeer.abv;
newBeer.image = currentBeer.image;
newBeer.save(function(err) {
if (err) {
throw err;
}
});
}
});
}
}
我想遍历每种啤酒并将其信息保存到数据库中。我使用findOne来防止重复,但这是行不通的。第一个console.log()语句打印每个啤酒ID,但是第二个console.log()语句多次打印最后一个啤酒ID。
最佳答案
这里的问题是在findOne
回调中-您的beerId
将始终设置为beerObjects
中的最后一个啤酒,因为循环会在您到达第一个回调之前完成-欢迎使用异步javascript。
一种解决方法是将您的findOne
代码包装在IFFE(立即调用函数表达式)中。该代码将在从beerObject移至下一个啤酒之前完成。
这是有关IFFE的更多信息
Stack Overflow on IFFE
我快速浏览了一下代码,我相信这应该可行,但是您可能必须对内部代码进行一些调整...
for(var i = 0; i < beerObjects.length; i++) {
console.log(beerObjects[i].beerId);
//var currentBeer = beerObjects[i]; dont need this now
(function (currentBeer) {
Beer.findOne({ beerId: currentBeer},
function(err, beer) {
if(!err && !beer) {
var newBeer = new Beer();
newBeer.beerId = currentBeer.beerId;
newBeer.name = currentBeer.name;
newBeer.description = currentBeer.description;
newBeer.abv = currentBeer.abv;
newBeer.image = currentBeer.image;
newBeer.save(function(err) {
// log your error here...
});
} else if(!err) {
console.log("Beer is in the system");
} else {
console.log("ERROR: " + err);
}
}
);
})(beerObjects[i].beerId);
}