Javascript 解决回调的更好方法

Javascript 解决回调的更好方法,javascript,node.js,asynchronous,promise,Javascript,Node.js,Asynchronous,Promise,我想做的是 1) 获取可用数据库的列表。 2) 获取每个数据库中存在的集合的列表 并在同一个API调用中执行这两项操作 我正在为节点使用MongoDB驱动程序。(require('mongodb');notmongoose) 我可以使用成功获取数据库列表 var adminDb = db.admin(); // db is the instance of my MongoDb server adminDb.listDatabases(function(err,dbs){ //dbs co

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

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

我正在为节点使用MongoDB驱动程序。(
require('mongodb');
notmongoose)

我可以使用成功获取数据库列表

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);
    });
}
exports.getDatabaseList=函数(req,res){ var adminDb=db.admin(); adminDb.listDatabases(函数(err,dbs){ 如果(错误){ res.json(err); }否则{ var result=dbs.databases.filterArray('local');//这将删除名为“local”的元素。我们不需要这些东西。 var len=结果长度-1; var计数=0; var check=len*((len+1)/2);//可用数据库数的算术预测。 对于(var i=0;i=1); 回调(项目、索引); }); } 如您所见,我正在查看结果(可用数据库的列表),获取其集合,然后将它们添加到响应对象

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

然而,这让我觉得,在我的后脑勺里仍然有一个bug,那就是这不是一个正确的方法,必须有更好的方法来跟踪在循环中被调用的回调的返回(因为缺少更好的词语和术语)

所以,我的问题是,有没有一种更优雅、更干净的方法来做这件事?这能在没有算术级数可怕的情况下完成吗

这对于10到15个条目来说很好,但是如果我有一个有1000个数据库的服务器呢

我还知道,稍后当用户从列表中选择数据库时,我可以获取集合列表。

我的主要问题是关于管理回调,而不是关于当前代码的设计。

如评论中所述,您可以使用优秀的异步库()来使用async
map
函数管理回调集合

但是,当您特别询问使用承诺的实现时,我建议您使用内置支持承诺数组的库

下面是一个使用“when”库()的示例:


这段代码的作用是获取一组数据库对象,将其中的每一个数据库传递给一个函数(
getCollectionsForDb
),该函数返回a。这将生成一个承诺数组,并在所有承诺都已解析(异步计算已完成,异步操作的结果已准备就绪)时生成承诺数组当库调用回调时,您可以在其中利用结果集合(在本例中,将其转储到控制台中)。

1000s数据库?循环将为O(n),所以你拥有的越多,它需要的时间就越长。这段代码中的承诺在哪里?或者你是在问如何使用承诺来设计它?你可以阅读该模块的源代码…它非常强大,解决了一系列问题(如订购)对你来说。当然,值得知道,如果你足够了解,你可以做出贡献!如果你要使用“承诺”一词,那么人们会认为你在谈论承诺。如果你不是这个意思,那么请编辑你的标题和问题,使用不同的术语。否则人们真的不知道你在问什么。你的代码使用现在许多系统内置的或通过库提供的实际承诺,您将受益匪浅。编辑:)也将研究承诺。您不应该忘记使用
err
ors拒绝
。是的,我在示例中添加了这一点。如果我是完美主义者,我也会添加超时处理。
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);
      });
});