0

I'm trying to calculate the amount of sign-ups of each day of the current month, and send that data to the Statistics page, where I display that data in a chart using Chart.js.

the data initialized well insides the query's scope, however I "lose" it outside of the scope.


EDIT - I extended my code so maybe there's some information relevant to my problem.


Here is my code:

async function getSignUps() {
    const query = { createAt: { $gt: date.getFirstDateOfMonth(), $lt: new Date() } };
    const projection = { createAt: 1, _id: 0 }; //can be added to find()
    var signUps = new Array(date.getDaysInMonth()).fill(0); //create empty array of days in current month

    Contractor_Users_Collection.find(query).project(projection).toArray(function (err, result) {
        if (err) throw err;
        // manipulte data to create array that the index indicates the day of month
        // the value indicates the amount of signups per that day of the month
        for (let i = 0, d = date.getFirstDateOfMonth(); i < result.length; i++, d.setDate(d.getDate() + 1)) {
            nextDate = new Date(d.getDate() + 1);
            if (d <= result[i]['createAt'] <= nextDate) {
                day = result[i]['createAt'].getDate() - 1;
                ++signUps[day];
            }
        }
        console.log('*****');
        console.log('signUps inside find : ' + signUps);
        console.log('*****');
    })
    console.log('*****');
    console.log('signUps outside find : ' + signUps);
    console.log('*****');
    return signUps;
};

router.get("/statistics",async (req, res) => {
    const signUps = await getSignUps();
    console.log('*****');
    console.log('signUps :' + signUps);
    console.log('*****');

    res.status(200).render("statistics", { signUps: signUps });
});

Here's the output :

*****
signUps outside find : 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
*****
*****
signUps :0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
*****
*****
signUps inside find : 1,3,3,5,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
*****
  • 2
    Does this answer your question? [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – Sebastian Simon May 06 '21 at 08:53
  • In your actual log, didn't `signUps outside find` come first, and `signUps inside find` later? – tevemadar May 06 '21 at 09:00
  • @tevemadar yeah my bad, you're right... my console was not cleared... ill fix it – Lior Elisberg May 06 '21 at 09:03
  • Then it's clearly the suggested duplicate: `Contractor_Users_Collection` builds some processing chain with those `.x().y().z()` calls, but that will actually run asynchronously and the callback gets invoked when it's done. While `.toArray()` returns immediately and thus in the next line you still see the array of zeros. – tevemadar May 06 '21 at 09:13
  • Use `await` before `Contractor_Users_Collection.find(query)` since the function is already `async` – Mir entafaz Ali May 06 '21 at 09:18
  • by the looks of it the entire function may be `async` because `toArray()` was async, so you may succeed with `await Contractor_Users_Collection.find(...`. Oh, I type slow. – tevemadar May 06 '21 at 09:21
  • @tevemadar thanks for replying, unfortunately it did not work. I will edit the post to add even more of my code, maybe it will shed more light on the solution. – Lior Elisberg May 06 '21 at 09:56

1 Answers1

0

I found the solution, hope it will help to others...

async function getSignUps() {
    const query = { createAt: { $gt: date.getFirstDateOfMonth(), $lt: new Date() } };
    const projection = { createAt: 1, _id: 0 }; //can be added to find()
    var signUps = new Array(date.getDaysInMonth()).fill(0); //create empty array of days in current month
    try {
        let result = Contractor_Users_Collection.find(query).project(projection)
        result = await result.toArray()
        // manipulte data to create array that the index indicates the day of month
        // the value indicates the amount of signups per that day of the month
        for (let i = 0, d = date.getFirstDateOfMonth(); i < result.length; i++, d.setDate(d.getDate() + 1)) {
            nextDate = new Date(d.getDate() + 1);
            if (d <= result[i]['createAt'] <= nextDate) {
                day = result[i]['createAt'].getDate() - 1;
                ++signUps[day];
            }
        }
        return signUps;
    } catch (error) {
        console.error(error)
        throw error
    }
};