解决回调的更好方法

时间:2015-08-26 15:39:23

标签: javascript node.js asynchronous promise

我想做的是 1)获取可用数据库的列表。 2)获取每个数据库中存在的集合列表。

在同一个API调用中执行这两项操作。

我正在使用Node的MongoDB驱动程序。 (require('mongodb');不是猫鼬)

我可以使用

成功获取数据库列表
var adminDb = db.admin(); // db is the instance of my MongoDb server
adminDb.listDatabases(function(err,dbs){
    //dbs contains information of available databases. 
}

现在在这个回调函数中。我获取每个数据库名称并获取它的集合。像

exports.getDatabaseList = function(req, res) {
    var adminDb = db.admin();
    adminDb.listDatabases(function(err,dbs){
        if(err){
            res.json(err);
        } else {
            var result = dbs.databases.filterArray('local'); // This will remove the element that has name 'local'. We don't need that shit.
            var len = result.length-1;
            var count = 0;
            var check = len*((len+1)/2); // Arithmetic progresion for the number of databases available.

            for(var i=0;i<result.length;i++){
                var dbName = result[i].name;

                getCollectionsForDb(dbName, i, function(collections, index){
                    result[index].collections = collections;
                    count+=index;
                    if(count === check){
                        res.json({content:result});
                    }
                });
            }
        }
    });
};

unction getCollectionsForDb(dbName, index, callback){
    var _db = db.db(dbName);
    _db.listCollections().toArray(function(err, items) {
        test.ok(items.length >= 1);
        callback(items, index);
    });
}

正如您所看到的,我正在查看结果(可用数据库列表)并获取它的集合,然后将它们添加到响应对象。

由于我从循环中进行异步调用,因此没有可靠的方法来确定是否返回了所有回调。 所以我维护一个变量check,它是结果数组length - 1的算术级数 我还构造了一个闭包,其中我在循环中传递当前索引,并在向调用函数返回相同的索引时。 当控件返回调用函数时,我将此索引添加到count变量中 因此,当count的值等于check时,我就会知道返回所有回调,现在可以安全地将响应发送回客户端。

然而,这让我觉得genuis,我脑子里仍然有一个错误,这不是一个正确的方法,并且必须有一个更好的方法来跟踪被调用的回调的返回在循环中(缺乏更好的单词和术语)

所以,我的问题是,是否有更优雅和干净的方式来做到这一点?这可以在没有算术级数的真棒的情况下完成吗? :d

这适用于10 15个条目,但如果我的服务器有1000个数据库怎么办?

我也知道,当用户从列表中选择数据库时,我可以稍后获取收集列表 我的主要问题是关于管理回调而不是关于当前代码的设计。

1 个答案:

答案 0 :(得分:0)

如评论中所述,您可以使用优秀的异步库(https://github.com/caolan/async)来使用异步map函数管理回调集合。

但是,当你特别询问使用promises的实现时,我建议使用一个内置支持promises数组的库。

这是一个使用&#34;当&#34;库(https://github.com/cujojs/when):

when.map(dbs.databases, getCollectionsForDb).done(function(collection) {
    // use your results here  
    console.log(collection);
});

function getCollectionsForDb(db){
    return when.promise(function(resolve, reject)) {
      db.listCollections().toArray(function(err, items) {
         if (err || items.length == 1) {
              reject("describe your error here");
         }
         resolve(items);
      });
});

此代码的作用是获取数据库对象的集合,将每个数据库对象传递给返回promise的函数(getCollectionsForDb)。这会生成一个promises数组,当所有的promise都已解析(异步计算完成,异步操作的结果准备就绪)时,when库会调用回调,然后你可以利用结果集合(in这个例子将它转储到控制台中。)