YAM
YAM

Reputation: 494

call back inside callback in nodejs?

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

Answers (2)

chridam
chridam

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

Jonathan Muller
Jonathan Muller

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

Related Questions