I've got a problem with my nodejs script and async library.
Ive got an async.auto with 2 parts. First part ok, in second part I've got another async.auto with 2 parts which are nearly the same, some changes in sql queries and arrays. But the first part here works fine, the second one the zutKopf stops with failure that the callback function cbzutk is not a function. Ive tried to fixed it somedays but can't find out the failure because its written like the first part zubKopf.
Hopefully u can help me.
Greets
async.auto({
one: function(cbone){
db.getConnection(function(err, dbs){
dbs.query("insert into rezepte (kat_id, rez_name, rez_desc, rez_img) values(?,?,?,?)",[RezeptComp.rezept.kat_id,RezeptComp.rezept.rez_name,RezeptComp.rezept.rez_desc,RezeptComp.rezept.rez_img],function(err, rows) {
if (err) {
cbone(err);
return;
}
console.log('query Rezept');
rezeptId = rows.insertId;
RezeptComp.rezept.rez_id = rows.insertId;
dbs.release();
cbone(null);
});
});
},
two: ['one', function(cbtwo){
async.auto({
zubKopf: function(cbzubk){
async.eachSeries(RezeptComp.zubereitung, function(data,next){
db.getConnection(function(err,dbzubk){
dbzubk.query("insert into zubereitungKopf (rez_id, zubk_text) values("+ rezeptId +",'"+ data.zubk_text +"')",function(err, rows) {
if (err) {
cbtwo(err);
return;
}
console.log('query zubk');
zubkId = rows.insertId;
RezeptComp.zubereitung[zubkd].zubk_id = zubkId;
dbzubk.release();
async.eachSeries(data.zubp, function(data2,next2){
db.getConnection(function(err,dbzubp){
dbzubp.query("insert into zubereitungPos (zubk_id, zubp_text) values("+ zubkId +",'"+ data2.zubp_text +"')",function(err, rows) {
if (err) {
cbtwo(err);
return;
}
console.log('query zubp');
zubpId = rows.insertId;
RezeptComp.zubereitung[zubkd].zubp[zubpd].zubp_id = zubpId;
dbzubp.release();
zubpd = zubpd + 1;
next2(null);
});
});
}, function(err, results){
zubkd = zubkd + 1;
zubpd = 0;
next(null);
});
});
});
}, function(err, results){
cbzubk(null);
});
},
zutKopf: ['zubKopf', function(cbzutk){
async.eachSeries(RezeptComp.zutaten, function(data3,next3){
db.getConnection(function(err,dbzutk){
dbzutk.query("insert into zutatenKopf (rez_id, zutk_text) values("+ rezeptId +",'"+ data3.zutk_text +"')",function(err, rows) {
if (err) {
cbzutk(err);
return;
}
console.log('query zutk');
zutkId = rows.insertId;
RezeptComp.zutaten[zutkd].zutk_id = zutkId;
dbzutk.release();
async.eachSeries(data3.zutp, function(data4,next4){
db.getConnection(function(err,dbzutp){
dbzutp.query("insert into zutatenPos (zutk_id, zutp_text) values("+ zutkId +",'"+ data4.zutp_text +"')",function(err, rows) {
if (err) {
cbzutk(err);
return;
}
console.log('query zutp');
zutpId = rows.insertId;
RezeptComp.zutaten[zutkd].zutp[zutpd].zutp_id = zutpId;
dbzutp.release();
zutpd = zutpd + 1;
next4(null);
});
});
}, function(err, results){
zutkd = zutkd + 1;
zutpd = 0;
next3(null);
});
});
});
}, function(err, results){
cbzutk(null);
});
}],
final: ['zubKopf', 'zutKopf', function(error, results){
cbtwo(null);
}]
});
}],
final: ['one', 'two', function(error, results){
callback(RezepComp);
}]
});
In async.auto depending functions receive as first a parameter from the previous function and then you can define the callback in the functionheader like two: ['one', function(parameter, callback) instead of two: ['one', function(callback).
Related
I am trying to develop an APP in which I have to increase or decrease the user count according to their hobbies/interest in the master list. I am doing it in Node js with the help of loopback. Here is my code, in which I am giving two interests(i.e sketching and horse-riding):
async.forEach(data, function (interest) {
console.log("Interest is", interest);
Interest.findOne({
where:
{
'name': interest
}
}, function (err, interestObj) {
if (err) {
//return callback(err, null);
console.log("error", err);
}
else {
//return callback(null, response);
console.log("found", interestObj);
if (!interestObj) {
Interest.create({ "name": interest, "count": 1 }, function (err, response) { });
}
else {
_count = interestObj.count + 1;
interestObj.updateAttribute('count', _count, function (e, r) { });
}
}
});
// return callback(null, {});
},function(err){
console.log("success..!!")
});
}
but it is showing me only one of them in output. Here is output:
data is [ 'horse-riding', 'skeching' ]
Interest is horse-riding
Interest is skeching
found { name: 'horse-riding', count: 1, id: 59ccff0765055a212491a6bc }
found null
I think the async function is not working properly with forEach loop in this, But I am not getting where the code went wrong. I want to show all the interest given by the user, so what course of actions should I take to do it?? Thanks in advance..!!:)
It is working now...!!!
async.each(data, function (interest, callback2) {
console.log('Processing ', interest);
Interest.findOne({
where:
{
'name': interest
}
}, function (err, interestObj) {
if (err) {
console.log("error", err);
callback2(err);
}
else {
console.log("found", interestObj);
if (!interestObj) {
Interest.create({ "name": interest, "count": 1 }, function (err, response) { });
}
else {
_count = interestObj.count + 1;
interestObj.updateAttribute('count', _count, function (e, r) { });
}
callback2();
}
});
}, function (err) {
if (err) {
console.log('Failed to process', err);
} else {
console.log('All interests have been processed successfully');
}
return callback(err);
})
};
I have a function which uses async.parallel function to call two functions. But I don't know how to handle errors when async.parallel is used. If one of the two functions throw errors, how do I handle them?
exports.getProductconfigWithProductList = function(req, res){
var apiVersion = req.param('version', null);
var product_id = req.params.productId;
dbDriver = determineDriver('es');
async.parallel([
function(callback) {
dbDriver.getProductconfig(product_id,function(data){
callback(null, data);
});
},
function(callback) {
var productListPromise = getProductListData();
productListPromise.then(function(data) {
callback(null, data);
});
}
],
function(err, results) {
if(!err){
var data = results[0];
data[1] = results[1];
res.send(data);
res.end();
} else {
console.log('<<<<<<<<<<<<<<'+err+'>>>>>>>>>>>>>>>');
res.send(err);
res.end();
}
}
);
};
When you have:
async.parallel([
func1,
func2,
], (err, data) => {
if (err) {
// you handle the errors here
}
});
It's explained in more detail in the docs:
https://caolan.github.io/async/docs.html
and in the issue on GitHub here:
https://github.com/caolan/async/issues/334
I'm having trouble getting to use the query mongodb.
I do not know if I could detail the method used is being sent an object, but is being rejected or sometimes the filter back empty.
it always returns me an error:
MongoError: query selector must be an object
The entry of the query is being thereby:
{ filter: 'f', limit: '5', page: '1', sort: '-posted' }
My server Route:
exports.findAll = function(req, res, next) {
var locals = {},
section = req.params.section,
query = req.query,
filter = {};
if(query.filter) {
filter = query.filter.replace(/"(\w+)"\s*:/g, '$1:');
filter = filter.replace(/["]/g, "'");
}
console.log(filter);
delete query.filter;
async.series([
function(callback) {
MongoClient.connect(url, function(err, db) {
if (err) return callback(err);
locals.collection = db.collection(section);
callback();
});
},
function(callback) {
locals.collection.count(filter, function (err, result){
if (err) return callback(err);
locals.count = result;
callback();
});
},
function(callback) {
//var cursor = locals.collection.find(filter);
var cursor = locals.collection.find(filter, req.query);
// if(req.query.order) {
// cursor = cursor.sort();
// }
//
// if(req.query.limit) {
// cursor = cursor.limit(Math.abs(req.query.limit));
//
if(req.query.page) {
cursor = cursor.skip(Math.abs(req.query.limit) * --req.query.page);
}
// }
cursor.toArray(function(err, docs) {
if (err) return callback(err);
locals.docs = docs;
callback();
});
}
],
function(err) { //This function gets called after the three tasks have called their "task callbacks"
if (err) return next(err);
// Here locals will be populated with 'count' and 'docs'
res.json({
count: locals.count,
data: locals.docs
});
});
};
i change the function server, adn now my response is:
{ filter: {situation: 't'}, limit: '5', page: '1', sort: '-posted' }
And same error :( :(
I am writing the filter using mongodb native driver, but it's driving me this error when you run the query.
In the case of this driver, it has no exec?
What is another way to perform this query?
exports.findAll = function(req, res) {
MongoClient.connect(url, function(err, db) {
var section = req.params.section;
var collection = db.collection(section);
var filter = req.query.filter ? {nameToLower: new RegExp('^' + req.query.filter.toLowerCase())} : {};
var query = collection.find(filter);
var count = 0;
collection.count(filter, function (error, result) {
count = result;
});
if(req.query.order) {
query.sort(req.query.order);
}
if(req.query.limit) {
query.limit(req.query.limit);
if(req.query.page) {
query.skip(req.query.limit * --req.query.page);
}
}
query.exec(function (error, results) {
res.json({
count: count,
data: results
});
});
});
};
Error:
TypeError: undefined is not a function
Better to use the async library in this case as it simplifies the code. In the case where you need to run multiple tasks that depend on each other and when they all finish do something else, use the
async.series() module. The following demonstrates how you can go about this in your case:
exports.findAll = function(req, res) {
var locals = {},
section = req.params.section,
filter = !!req.query.filter ? {nameToLower: new RegExp('^' + req.query.filter.toLowerCase())} : {};
async.series([
// Connect to DB
function(callback) {
MongoClient.connect(url, function(err, db) {
if (err) return callback(err);
locals.collection = db.collection(section); //Set the collection here, so the next task can access it
callback();
});
},
// Get count
function(callback) {
locals.collection.count(filter, function (err, result){
if (err) return callback(err);
locals.count = result; //Set the count here
callback();
});
},
// Query collection
function(callback) {
var cursor = locals.collection.find(filter);
if(req.query.order) {
cursor = cursor.sort(req.query.order);
}
if(req.query.limit) {
cursor = cursor.limit(req.query.limit);
if(req.query.page) {
cursor = cursor.skip(req.query.limit * --req.query.page);
}
}
cursor.toArray(function(err, docs) {
if (err) return callback(err);
locals.docs = docs;
callback();
});
}
], function(err) { //This function gets called after the three tasks have called their "task callbacks"
if (err) return next(err);
// Here locals will be populated with 'count' and 'docs'
res.json({
count: locals.count,
data: locals.docs
});
res.render('user-profile', locals);
});
};
At the moment I'm running this task:
var skip = 0;
var limit = 5;
gulp.task('add coordinates to visits', function(done) {
(function recurse() {
Visit.find({})
.skip(skip)
.limit(limit)
.populate('zone')
.exec(function cb(err, visits) {
if (err) {
throw err;
}
if (visits.length === 0) {
return;
}
async.each(visits, function iterateEvents(visit, next) {
if (!visit.zone) {
return next();
} else if (!visit.coordinates.lat || !visit.coordinates.lng) {
visit.coordinates = {
lat: visit.zone.geo.coordinates.lat,
lng: visit.zone.geo.coordinates.lng
};
}
visit.save(next);
}, function cb(err) {
if (err) {
throw err;
}
skip += limit;
setTimeout(recurse, 1000);
});
});
})();
});
But I'm sure there must be a more elegant and optimal method than using skip, limit, `setTimeout. Is there some mongo or mongoose method for running updating tasks?
Based on our conversation in the comments it seems like Mongoose's querystream might be what you are looking for:
var stream = Visits.find().populate('zone').stream();
stream.on('data', function processDoc(visit) {
var self = this;
if (visit.zone && (!visit.coordinates.lat || !visit.coordinates.lng)) {
self.pause();
visit.update({
coordinates: {
lat: visit.zone.geo.coordinates.lat,
lng: visit.zone.geo.coordinates.lng
}
}, function(err, result) {
if (err) { console.log(err); };
self.resume();
});
}
});
stream.on('error', function(err) {
console.log('error', err);
});
stream.on('close', function() {
console.log('closed');
});