Reputation:
Just started to play around with node.js, have some past experience with JavaScript but very little in server-side.
I have the below code and the functionality that I'm looking for is too add a product to the collection using Mongoose, however, if a duplicate is found using 'name', then push the product as an embedded document to the duplicate, with only select information, such as product_ids, package info, etc. I'm assuming that the problem has to do with findOne not finding any duplicates on the first run. If I run it a second time, it does detect the duplicates, but by then it's too late. I'm not sure how to get findOne to run only after the previous 'save' occurred.
function insertProduct(data) {
var product;
Product.findOne({
name: data.name
}, function(err, doc) {
if (err) throw err;
if (!doc) {
product = new Product({
name: data.name
//other product data
});
product.packages.push({
//package data
});
}
else if (doc) {
doc.packages.push({
//package data
});
product = doc;
}
product.save(function(err) {
if (err) throw err;
console.log('Added: ' + product.name);
});
});
}
request(url, function(error, response, body) {
if (!error && response.statusCode === 200) {
jsonResult = JSON.parse(body);
jsonResult.result.forEach(insertProduct);
}
});
I realize this has to be an issue with control flow, that I'm still trying to get a hold of. Your help is appreciated!
Upvotes: 3
Views: 961
Reputation: 2104
Welcome to the world of non-blocking IO, and JavaScript closures :)
A simpler way around it is by separating the product creation and push the packages after the product is successfully created.
addProduct = function(name, next) {
Product.findOne({name: name}, function(err, doc) {
if(doc) {
next(null, doc);
}
else {
// create new product...
var d = new Product({name: name});
next(null, d);
}
});
});
// ... snipped
jsonResult.result.forEach(function(item) {
addProduct(item.name, function(err, doc) {
if(err == null) {
doc.packages.push({
// stuffs
});
doc.save();
}
});
});
Upvotes: 1