Javascript Array.push在承诺函数中不起作用

Javascript Array.push在承诺函数中不起作用,javascript,arrays,node.js,promise,Javascript,Arrays,Node.js,Promise,我有一个像这样的nodejs Mongodb代码。我试图进入一个全局数组并返回所有结果,但该数组只包含一个值。知道为什么吗 var s = []; var p = function(){ return new Promise(function(resolve, reject) { MongoClient.connect(url, function (err, db) { db.listCollections().forEach(function(collname) { d

我有一个像这样的nodejs Mongodb代码。我试图进入一个全局数组并返回所有结果,但该数组只包含一个值。知道为什么吗

var s = [];
var p = function(){
return new Promise(function(resolve, reject) {
    MongoClient.connect(url, function (err, db) {

   db.listCollections().forEach(function(collname) {

   db.collection(collname.name).find().sort( { duration_in_seconds: 1 }).limit(1).toArray(

  function(err, docs) {

        assert.equal(null, err);
        s.push(docs);
        resolve();
      });


});

 });

});

}


p().then(function() {

  console.log(s);

});

当第一个集合返回其文档时,您正在解析承诺。你需要等他们所有人。不要将所有内容都包装在一个大的
新承诺中,而是每个异步函数都有自己的承诺,并使用结果值实现返回的承诺,而不是将其放入全局变量中:

function connect(url) {
    return new Promise(function(resolve, reject) {
        MongoClient.connect(url, function (err, db) {
            if (err) reject(err);
            else resolve(db);
        });
    });
}
function getArray(cursor) {
    return new Promise(function(resolve, reject) {
        cursor.toArray(function(err, docs) {
            if (err) reject(err);
            else resolve(docs);
        });
    });
}
现在,您可以使用这些帮助程序编写
p
,将每个集合的承诺放在一个数组中,然后等待它们,这将为所有结果的数组生成一个正确的承诺:

function p() {
    return connect(url).then(function(db) {
        return getArray(db.listCollections()).then(function(collections) {
            var promises = collections.map(function(collname) {
                return getArray(db.collection(collname.name).find().sort({duration_in_seconds: 1 }).limit(1));
            });
            return Promise.all(promises);
        });
    });
}

p().then(function(s) {
    console.log(s);
});

当第一个集合返回其文档时,您正在解析承诺。你需要等他们所有人。不要将所有内容都包装在一个大的
新承诺中,而是每个异步函数都有自己的承诺,并使用结果值实现返回的承诺,而不是将其放入全局变量中:

function connect(url) {
    return new Promise(function(resolve, reject) {
        MongoClient.connect(url, function (err, db) {
            if (err) reject(err);
            else resolve(db);
        });
    });
}
function getArray(cursor) {
    return new Promise(function(resolve, reject) {
        cursor.toArray(function(err, docs) {
            if (err) reject(err);
            else resolve(docs);
        });
    });
}
现在,您可以使用这些帮助程序编写
p
,将每个集合的承诺放在一个数组中,然后等待它们,这将为所有结果的数组生成一个正确的承诺:

function p() {
    return connect(url).then(function(db) {
        return getArray(db.listCollections()).then(function(collections) {
            var promises = collections.map(function(collname) {
                return getArray(db.collection(collname.name).find().sort({duration_in_seconds: 1 }).limit(1));
            });
            return Promise.all(promises);
        });
    });
}

p().then(function(s) {
    console.log(s);
});

您不能像这样引用承诺范围之外的变量。改为在“内部”使用它。你能解释一下怎么做吗?我对承诺不熟悉@NeilLunn@NeilLunn这里的问题不是承诺,而是
forEach
循环,您不能引用承诺范围之外的变量。改为在“内部”使用它。你能解释一下怎么做吗?我对承诺不熟悉@NeilLunn@NeilLunn这里的问题不是承诺,而是forEach循环,非常感谢您的解决方案。我试过了,但是我得到了这个错误“TypeError:db.listCollections(…).map不是函数”噢,drat,我希望
listCollections
返回一个数组(使用标准
forEach
map
方法),而不是需要等待的异步游标。但我们也可以适应。哦,是的,我就是这么想的。它成功了谢谢你Bergit非常感谢你的解决方案。我试过了,但是我得到了这个错误“TypeError:db.listCollections(…).map不是函数”噢,drat,我希望
listCollections
返回一个数组(使用标准
forEach
map
方法),而不是需要等待的异步游标。但我们也可以适应。哦,是的,我就是这么想的。成功了谢谢你,伯吉