在nodejs中回调内部回调?

时间:2016-03-05 12:07:13

标签: node.js mongodb

我有以下nodejs代码:

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});
    });
    });
  });

在这里,我必须添加更多两个或三个查询/回调。

但我不认为这是正确的做法。 请任何人告诉我如何解决这个问题以提高性能。

谢谢

2 个答案:

答案 0 :(得分:4)

在这种情况下,使用async / await将是一个合适的解决方案,可以避免回调地狱。考虑按如下方式运行查询:

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)
    }
}

作为替代方案,当您需要运行多个不依赖的任务时,您可以使用 async 库,尤其是 async.parallel() 方法彼此之间以及当他们都完成其他事情时。

考虑以下示例:

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);
    });
});

答案 1 :(得分:3)

您可以将本机Promise与MongoDB驱动程序一起使用(在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接受你提供的承诺并同时执行它们。

  

Promise.all(iterable)方法返回一个promise,它在iterable参数中的所有promise都已解析时解析

来源: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

(顺便说一下,我认为你应该用更多类似'改进独立嵌套异步调用'的方式重命名你的问题,以避免你的关闭/重复问题。)