2

I have this code that takes the value of the number of documents on a given day of the week in MongoDB. And as a return request, the "qweek" array is filled.

function dates(current) {
  var week = new Array();

  // Starting Monday not Sunday
  current.setDate((current.getDate() - current.getDay() + 1));

  for (var i = 0; i < 7; i++) {
    var dd = String(current.getDate()).padStart(2, '0');
    var mm = String(current.getMonth() + 1).padStart(2, '0'); //January is 0!
    var yyyy = current.getFullYear();
    var day = dd + '/' + mm + '/' + yyyy;

    week.push(day);

    current.setDate(current.getDate() + 1);
  }

  return week;
}

// Initialize the App Client
const client = stitch.Stitch.initializeDefaultAppClient("app-id");

// Get a MongoDB Service Client
const mongodb = client.getServiceClient(
  stitch.RemoteMongoClient.factory,
  "mongodb-atlas"
);

//projection config
const options = { // Match the shape of RemoteFindOptions.
  limit: 1000, // Return only first ten results.
  projection: { // Return only the `title`, `releaseDate`, and
    day: 1, //   (implicitly) the `_id` fields.
  },
  sort: { // Sort by releaseDate descending (latest first).
    releaseDate: -1,
  },
}

// Get a reference to the travels database
const db = mongodb.db("travels");

function displayCountTravels() {
  var daysweek = dates(new Date());
  var qweek = new Array();

  for (var l = 0; l < daysweek.length; l++) {
    db.collection("details")
      .find({
        "day": daysweek[l]
      }, options)
      .toArray()
      .then(docs => {
        qweek.push(docs.length);
      });
  }

  console.log(qweek);
  console.log(qweek[1]);

  return qweek;
}

In this case, when I make a request in the array console. I get this return:

console.log(qweek);
Log output:[]
0: 0
1: 0
2: 0
3: 2
4: 0
5: 0
6: 0
length: 7
__proto__: Array(0)

Return of command console.log(week);

Return of command "console.log(week);"

But when I try to get the value by the index. The array item is returned with undefined.

console.log(qweek[1]);

Log output:

undefined

Return of command console.log(week[1]);

Return of command "console.log(week[1]);"

I would like to know why the value comes with undefined.

4
  • 1
    I think it'd be helpful if you could provide the output of your console logs in plain text, rather than as an image. Thanks! Commented Apr 9, 2020 at 14:02
  • 1
    Also, please update the question with full code to understand the scenario better, specifically where you console print the values. Most likely what is happening is: the console.log of qweek is inside the then() block and console.log(qweek[1]); is outside. Commented Apr 9, 2020 at 14:14
  • 1
    @finferflu ty for the advice ^^ Commented Apr 9, 2020 at 14:37
  • @ambianBeing Thanks for the advice. I did what you asked. Yes, I tried to put qweek out of then. But the values did not return or returned equal to zero. I tried to put a variable in place and feed the array outside the then as well. Ex: then (docs => var daycount = docs.length); and outside then qweek.push (daycount); Commented Apr 9, 2020 at 14:43

1 Answer 1

1

Essentially this is a case of asynchronous behavior in Javascript. On top of that asynchronous calls are made in a for..loop.

Short explanation: The mongo-db query calls are async in nature and the execution is not going to wait for it finish before reaching the console.log(qweek) which is outside the then block. As a result you'll be getting qweek as empty[] or qweek[1] as undefined.

Couple of ways solve this is Serializing with promises and async/await or using Promise.all(). Would suggest you to read upon them to understand more.

Using async/await: Syntax wise less verbose and easy to comprehend

async function displayCountTravels() {
  var daysweek = dates(new Date());
  var qweek = [];
  try {
    for (var l = 0; l < daysweek.length; l++) {
      /*wait for the promise to resolve before next iteration*/
      var docs = await db
        .collection("details")
        .find({ day: daysweek[l] }, options).toArray();

      qweek.push(docs.length);
    }
  } catch (e) {
    console.error(e);
  }

  console.log(qweek);
  console.log(qweek[1]);

  return qweek;
}

Using Promise.all(...):

function displayCountTravels() {
  var daysweek = dates(new Date());
  var promises = [];

  /*each mongo query is a promise, collect and return*/

  for (var l = 0; l < daysweek.length; l++) {
    promises.push(
      db.collection("details").find({ day: daysweek[l] }, options).toArray()
    );
  }

  return Promise.all(promises);
}

/*Calling fn, getting results in then since Promise.all() itself is promise*/
displayCountTravels()
  .then((results) => {
    /*using map to get lengths of the documents returned and put it in qweek*/
    var qweek = results.map((e) => e.length);
    console.log(qweek);
    console.log(qweek[1]);
  })
  .catch((e) => {
    console.error(e);
  });
Sign up to request clarification or add additional context in comments.

3 Comments

Thaank you so much for help. You're saving my day :D @ambianBeing hahaha. I am trying to implement both options. But in both I am getting the following error. dashboard.html: 110 Uncaught TypeError: db.collection (...). find (...). exec is not a function. How can I solve the problem related to Exec ()? And what is it for? Sorry for many questions haha ': D.
@JoãoGabrielAraujo Sorry my bad. Habit of writing ..since I've use mongoose with mongodb and there exec() is used to get full fledged promise. And Though u were using the same. Clearly you are not, in native mongo with node the queries are promises( no need of .exec()). Yon can remove the .exec(). I've updated the answer. And you are most welcome. Let me know if this works.
OMG, OMG. The first solution WORKS!!!! Thank you sooo much. OMG. that's a man, that's a man!! HaHa. I just switch exec() to .toArray();

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.