1
const returnPostData = async (req, res, initialPostsQueryArray) => {
    const promises = initialPostsQueryArray.map((post) => {

        let postObject;

        voteCount = sumValues(post.voting_options);
        pool.query('SELECT voting_option FROM votes WHERE user_id = $1 AND post_id = $2', 
            [req.user.userId, post.post_id], 
            (error, results) => {
                if (error) {
                    console.log(error);
                    return res.json({'Error': error.detail});
                }
                userVoteOption = results.rows[0].voting_option;
        });
        postObject.voteCount = voteCount;
        postObject.userVoteOption = userVoteOption;
        return postObject;
    });

    return Promise.all(promises).then(postData => {
        return res.json(postData);
    })
}

I'm trying to return an array of the postObjects for each post. For some reason it keeps on printing null for these objects because the return res.json is somehow running before the promises are even done. Any help is appreciated.

I had this problem before and used the same code, but it didn't work for this one for some reason.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
frankied003
  • 466
  • 6
  • 26
  • I've rolled back the edit and will discuss the new code in [your new question](https://stackoverflow.com/questions/65587575/multiple-queries-in-a-map-function) – Bergi Jan 05 '21 at 22:42

1 Answers1

2

Multiple problems:

  • You return postObject before userVoteOption is assigned
  • You don't actually use promises with node-postgres
  • …and therefore the return value of the map callback is not a promise
  • You never initialse postObject
  • You marked your function as async but never use await
  • You handle each error in the loop individually (which leads to res.json being called multiple times in case of multiple errors)

To fix these, use

async function returnPostData(req, res, initialPostsQueryArray) {
    try {
        const promises = initialPostsQueryArray.map(async (post) => {
            const voteCount = sumValues(post.voting_options);
            const results = await pool.query(
                'SELECT voting_option FROM votes WHERE user_id = $1 AND post_id = $2', 
                [req.user.userId, post.post_id]
            );
            const userVoteOption = results.rows[0].voting_option;
            const postObject = { voteCount, userVoteOption };
            return postObject;
        });
        const postData = await Promise.all(promises);
        res.json(postData);
    } catch(error) {
        console.log(error);
        res.json({'Error': error.detail});
    }
}

In addition, you actually shouldn't use a loop at all here. Just query multiple rows from postgres at once! Using this approach to supply the ids:

async function returnPostData(req, res, initialPostsQueryArray) {
    try {
        const voteCounts = new Map();
        const ids = [];
        for (const post of initialPostsQueryArray) {
            ids.push(post.post_id);
            voteCounts.set(post.post_id, sumValues(post.voting_options));
        }
        const {rows} = await pool.query(
            'SELECT post_id, voting_option FROM votes WHERE user_id = $1 AND post_id = ANY($2::int[])', 
            [req.user.userId, ids]
        );
        const postData = rows.map(row => {
            const postObject = {
                voteCount: voteCounts.get(row.post_id),
                userVoteOption: row.voting_option,
            };
            return postObject;
        });
        const postData = await Promise.all(promises);
        res.json(postData);
    } catch(error) {
        console.log(error);
        res.json({'Error': error.detail});
    }
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thank you for your help. I did some deleting and typing into stack so some things got messed up. My main goal was to figure out why null was printing out and i see how you did "const postData = await Promise.all(promises); res.json(postData);" but I'm still unable to get that working. I have a lot of nested queries in the function that I didn't post here. Could it have something to do with that? – frankied003 Jan 05 '21 at 22:07
  • Sure could have something to do with that… You might [edit your question](https://stackoverflow.com/posts/65585755/edit) to update small things from your actual code, but if it's a substantial difference you better might want to [ask a new question](https://stackoverflow.com/questions/ask). – Bergi Jan 05 '21 at 22:18
  • In general, don't do lot of nested queries. Use SQL joins for better performance. – Bergi Jan 05 '21 at 22:18
  • I edited the code to be the entire function I currently have. Yes I'm a newbie at sql, my father told me the same thing. Moving from firestore to postgres so a little different lol. Thank you for your help! – frankied003 Jan 05 '21 at 22:21
  • You still haven't converted the `pool.query` calls to use promises instead of callbacks, so that you can `await` them in sequence. – Bergi Jan 05 '21 at 22:39