Kavija Karunarathna
Kavija Karunarathna

Reputation: 15

Data doesn't get pushed to the array nodeJS

So what I basically want to do is create a new array of users from existing mongoose documents. I have a users array in my database. Each user has a attribute booksBorrowed which is also a array and I need to replace this with another object retrieved from a Book Model. I know that I can use populate function to do this. But in the booksBorrowed array I have some other values like Date and a boolean. So I can't use that function. Please help me out :). Thanks in advance.

router.get("/users",isAdmin, function(req,res){
User.find({}, function(err, users){
    if (err){
        console.log(err);
    }
    else {
        var modifiedUsers = [];
        for (const user of users) {
            var booksBorrowed = [];
            function async pushBook(book) {
                await booksBorrowed.push(book)
            }
                if(user.booksBorrowed){
                    for (const book of user.booksBorrowed){
                        Book.findById(book[0], function(err, bookFound){
                            if(err){
                                console.log(err);
                            }
                            pushBook(bookFound);
                        });
                    };  
                } 
            console.log(booksBorrowed);
            user.booksBorrowed = booksBorrowed;
            modifiedUsers.push(user);
            };
        res.render("users", {users: modifiedUsers});
    }
});

When I console.log(booksBorrowed) All I see is a list of empty arrays. Maybe the variable doesn't get updated or the process of pushing doesn't complete and the rest of the code runs.

Upvotes: 0

Views: 36

Answers (1)

jfriend00
jfriend00

Reputation: 707318

There are a number of issues with your code. Primarily, it shows that you don't understand how await works and then probably don't understand how it relates to promises. Here are some points:

  1. await only does something useful when you await a promise that is linked to the asynchronous operation you're trying to wait on. So await booksBorrowed.push(book) does nothing useful.
  2. You never want to mix plain callbacks and promises/await so you should switch to the promise versions of your database calls to get rid of the plain callbacks in your code and then you can use the promises they return with await and for control flow.
  3. You must always send an http response, even in error conditions. So, all possible error code paths must still send an http response.
  4. Your modifiedUsers array looks like maybe there's a problem because the way your code is written, it's the exact same array as users since you add every single user to the modifiedUsers array. If you meant for it to be only users who have borrowed a book, then you will need clarify that in your question and adjust the logic to actually do that.
  5. Your logic also truncates the user.booksBorrowed array to only be the first item in that array. So if there is more than one book in that array, it will never be used and your code will replace user.booksBorrowed with only a single element array. This doesn't seem correct, but I don't know what logic you want this to be. I don't understand why you're replacing user.booksBorrowed in the first place.

Here's a rewritten version that addresses these first three issues:

router.get('/users', isAdmin, async function (req, res) {
    try {
        let users = await User.find({});
        let modifiedUsers = [];
        for (const user of users) {
            let booksBorrowed = [];
            if (user.booksBorrowed) {
                for (const book of user.booksBorrowed) {
                    let bookFound = await Book.findById(book[0]);
                    booksBorrowed.push(bookFound);
                }
            }
            user.booksBorrowed = booksBorrowed;
            modifiedUsers.push(user);
        }
        res.render('users', { users: modifiedUsers });
    } catch (e) {
        // log error and send error status
        console.log(e);
        res.sendStatus(500);
    }
});

Please, please read and learn about how promises work and how await works with promises and how your database can use promises. You will need to know this to write good solid code. This is one example, but you need to learn the concepts yourself.

Upvotes: 1

Related Questions