Reputation: 494
I have following nodejs code:
app.get('/dashboard', function(req, res){
db.collection('com_url_mamy').find().toArray(function(err, doc){
db.collection('com_url_mamy').find({'price':''}).count(function(err, docs){
db.collection('com_url_mamy').find({"price":{$not:{$ne:"last_price_1"}}}).count(function(err, last_doc){
if(err){console.log(err);}
console.log(docs);
res.render('dashboard',{'doc':doc, 'docs':docs, 'last_doc':last_doc});
});
});
});
Here i have to add more two or three query/callback.
But I don't think this is right way to do. Please any one can me tell me how I can solve this problem to increase performance.
Thank You
Upvotes: 2
Views: 676
Reputation: 103365
Using async/await will be an appropriate solution that avoids the callback hell for you in this case. Consider running your queries as follows:
app.get('/user/:name', async (req, res, next) => {
try {
const docs = await db.collection('com_url_mamy').find().toArray()
const count = await db.collection('com_url_mamy').find({'price':''}).count()
const last_doc = await db.collection('com_url_mamy').find({"price": "last_price_1"}).count()
res.render('dashboard', { docs, count, last_doc })
} catch (err) {
return next(err)
}
}
As an alternative, you can use the async libary especially the async.parallel()
method when you need to run multiple tasks that do not depend on each other and when they all finish do something else.
Consider the following example:
app.get('/user/:name', function(req, res, next) {
var locals = {};
async.parallel([
// Load all documents
function(callback) {
db.collection('com_url_mamy').find().toArray(function(err, docs){
if (err) return callback(err);
locals.docs = docs;
callback();
});
},
// Get count of documents where price is empty
function(callback) {
db.collection('com_url_mamy').find({'price':''}).count(function(err, count){
if (err) return callback(err);
locals.count = count;
callback();
});
},
// Load last docs
function(callback) {
db.collection('com_url_mamy').find({"price": "last_price_1"}).count(function(err, docs){
if (err) return callback(err);
locals.last_doc = docs;
callback();
});
}
], function(err) { //This function gets called after the three tasks have called their "task callbacks"
if (err) return next(err);
//Here render dashboard with locals object
res.render('dashboard', locals);
});
});
Upvotes: 4
Reputation: 7516
You can use native Promises with MongoDB driver (on node.js >= 0.12):
app.get('/dashboard', function(req, res){
var proms = [];
proms.push(db.collection('com_url_mamy').find().toArray());
proms.push(db.collection('com_url_mamy').find({'price':''}).count());
proms.push(db.collection('com_url_mamy').find({"price": "last_price_1"}).count());
Promise.all(proms)
.then(function(pres) {
res.render('dashboard',{'doc':pres[0], 'docs': pres[1], 'last_doc': pres[2]});
})
.catch(console.error);
});
Promise.all
takes the promises you give it and execute them in parallel.
The Promise.all(iterable) method returns a promise that resolves when all of the promises in the iterable argument have resolved
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
(BTW I think you should rename your question with something more like 'Improve independent nested async calls' to avoid the closing/duplicate issue you had.)
Upvotes: 3