0

I am using Node.js and MongoDB atlas which is an online db. I have established a connection to MongoDB atlas and sent a query to the database and retrieved a collection. the collection is returned without any errors. Now I am trying to push the results of the query to an array but the array is still empty.

I have tried to use the console.log() and I see the array becomes empty after the loop. I have noticed that the the second console.log is printed before. I don't know why.

const mongoose = require('mongoose');

var data = function () {

    var array = [];

    mongoose.connection.collection("organizations").find({}).toArray(function(err, result) {
        if (err) throw err;

        for(var i = 0; i < result.length; i++)
        {
            var a = result[i].name;
            array.push(a);
            console.log(array[i]); //this shows that the array is getting filled and the result is printed correctly.
        }

    });

    console.log(array); //this shows only [] meaning that the array is now empty.
                        //this is shown in the log before the first log
    return array;
};

module.exports = {
    data: data,
};
Kunal Mukherjee
  • 5,775
  • 3
  • 25
  • 53
Red Eyez
  • 187
  • 3
  • 16

3 Answers3

1

toArray is async - your're console.logging the empty array before the toArray call happens. Try this:

const mongoose = require('mongoose');

var data = async function () {

    const array = await mongoose.connection.collection("organizations").find({}).toArray(function(err, result) {
        if (err) throw err;
        return result.map(r => r.name);
    });

    console.log(array); //this shows only [] meaning that the array is now empty.
                        //this is shown in the log before the first log
    return array;
};

module.exports = {
    data: data,
};
Ziarno
  • 7,366
  • 5
  • 34
  • 40
  • `toArray()` is also using a "callback" in the code in your answer. So you **cannot** `await` a "callback". – Neil Lunn Apr 25 '19 at 12:45
1

Create connection and gettting information from table is asynchronous operations. It might take time to complete request. So you can handle asynchronous operations by using async/await and promise like below.

const mongoose = require('mongoose');
    var data = async function () {
         var array = [];
         const finalResults = await new Promise((resolve, reject) => {
            mongoose.connection.collection("organizations").find({}).toArray(function(err, result) {
              resolve(result);
           });
      });

     for(var i = 0; i < finalResults.length; i++)
     {
          var a = finalResults[i].name;
           array.push(a);
      }
        return array;
    };

    module.exports = {
        data: data,
    };

It might help you.

narayansharma91
  • 2,273
  • 1
  • 12
  • 20
0

You cannot return from an asynchronous callback, here .toArray() is a callback.

So modify your code to pass in a callback function which you can send the result.

Assuming this is written in mongooseModule.js

const mongoose = require('mongoose');

var data = function (callback) {

    var array = [];

    mongoose.connection.collection("organizations").find({}).toArray(function(err, result) {
        if (err) throw err;

        for(var i = 0; i < result.length; i++)
        {
            var a = result[i].name;
            array.push(a);
            console.log(array[i]); //this shows that the array is getting filled and the result is printed correctly.
        }

        callback(array);
    });
};

module.exports = {
    data: data,
};

And in your Express handler:

const mongooseModule = require('mongooseModule'); 

app.get('/someroute', function(req, res, next) {
    res.status(200);
    mongooseModule.data(res.json);
});
Kunal Mukherjee
  • 5,775
  • 3
  • 25
  • 53