0

I have a nodejs Mongodb code like this . I'm trying to push into a global array and return all my results but the array contains only one value . Any idea why ?

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

});
3
  • You cannot reference a variable outside of the scope of the promise like that. Work with it "inside" instead. Read the duplicate and understand it. Commented Jun 15, 2017 at 1:46
  • Can you please explain how ? I'm new to promises @NeilLunn Commented Jun 15, 2017 at 1:48
  • @NeilLunn the problem here is not the promise, it's the forEach loop Commented Jun 15, 2017 at 2:09

1 Answer 1

2

You are resolving the promise when the first collections returns its document. You'd need to wait for all of them. Instead of wrapping everything in a large new Promise, promisify every asynchronous function on its own, and make the returned promise fulfill with the result value instead of putting it in a global variable:

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

Now you can write your p using these helpers, put the promises for each collection in an array, and await them with Promise.all, which yields a promise right for the array of all results:

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);
});
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you so much for the solution . I tried it but i get this error "TypeError: db.listCollections(...).map is not a function "
Oh drat, I was expecting listCollections to return an array (with standard forEach and map methods), not an asynchronous cursor that needs to be awaited. But we can adjust to that as well.
Oh yea thats what I thought . It worked Thank you Bergi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.