Multiple queries in a .map function

孤者浪人 提交于 2021-01-07 01:36:16

问题


const returnPostData = async (req, res, initialPostsQueryArray) => {
    try{
        const promises = initialPostsQueryArray.map( async (post) => {
            let voteCount = 0;
            let voted = false;
            let liked = false;
            let userHandle;
            let userImageUrl;
            let votingOptionsDictionary;
            let userVoteOption;

            voteCount = sumValues(post.voting_options);
            pool.query('SELECT userhandle, image_url FROM users WHERE id = $1 ', 
                [post.user_id], 
                (error, results) => {
                    if (error) {
                        console.log(error);
                        return res.json({'Error': error.detail});
                    }
                    const userPostquery = results.rows[0];
                    userHandle = userPostQuery.userhandle;
                    userImageUrl = userPostQuery.image_url;
                    pool.query('SELECT EXISTS( SELECT 1 FROM likes 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});
                            }
                            // if the user like exists, set liked = true
                            if(results.rows[0].exists == true){
                                liked = true;
                            }
                            pool.query('SELECT EXISTS( SELECT 1 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});
                                    }
                                    // if the user vote exists, set voted = true and query for what they voted for
                                    if(results.rows[0].exists == true){
                                        voted = true;
                                        votingOptionsDictionary = 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;
                                        });
                                    }
                                    // i dont need voteCount here because that is calculated after the first query, this gets all the counts of the posts
                                    pool.query('SELECT posts.post_id, ' +
                                        'COALESCE( likes.cnt, 0 ) AS like_count ,' +
                                        'COALESCE( comments.cnt, 0 ) AS comment_count ,' +
                                        'COALESCE( shares.cnt, 0 ) AS share_count ' +
                                        'FROM posts ' +
                                        'LEFT JOIN ( SELECT post_id, COUNT(*) AS cnt FROM likes GROUP BY post_id ) likes ON posts.post_id = likes.post_id ' +
                                        'LEFT JOIN ( SELECT post_id, COUNT(*) AS cnt FROM comments GROUP BY post_id ) comments ON posts.post_id = comments.post_id ' +
                                        'LEFT JOIN ( SELECT post_id, COUNT(*) AS cnt FROM shares GROUP BY post_id ) shares ON posts.post_id = shares.post_id ' +
                                        'WHERE posts.post_id = $1',
                                        [post.post_id],
                                        (error, results) => {
                                            if (error) {
                                                console.log(error);
                                                return res.json({'Error': error.detail});
                                            }
                                            const countQuery = results.rows[0];

                                            // final response once all above queries are done, i dont account for thread comments in comment count rn, later problem
                                            return {
                                                postId: post.post_id,
                                                userHandle: userHandle,
                                                userImageUrl: userImageUrl,
                                                postQuestion: post.post_question,
                                                imageUrl: post.post_image_url,
                                                postDescription: post.post_description,
                                                votingOptions: Object.keys(post.voting_options),
                                                voted: voted,
                                                userVoteOption: userVoteOption,
                                                liked: liked,
                                                votingOptionsDictionary: votingOptionsDictionary,
                                                voteStat: voteCount,
                                                likeCount: parseInt(countQuery.like_count),
                                                shareCount: parseInt(countQuery.share_count),
                                                commentCount: parseInt(countQuery.comment_count),
                                                createdAt: post.created_at
                                            };
                                    });
                            });
                    });
            });
        });
        const postData = await Promise.all(promises);
        return res.json(postData);
    }
    catch(e){
        return res.json(e)
    }
}

I'm trying to return an array of the postData 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.


回答1:


You're still not using promises but pass callbacks to query. You cannot return from those, and they won't be awaited by Promise.all. You are looking for

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 userhandle, image_url FROM users WHERE id = $1 ', 
                [post.user_id],
            ]);
            const userPostquery = results.rows[0];
            const userHandle = userPostQuery.userhandle;
            const userImageUrl = userPostQuery.image_url;
            
            const {rows: likes } = await pool.query(
                'SELECT EXISTS( SELECT 1 FROM likes WHERE user_id = $1 AND post_id = $2)',
                [req.user.userId, post.post_id],
            );
            // if the user like exists, set liked = true
            const liked = likes[0].exists;

            const {rows: votes} = await pool.query(
                'SELECT EXISTS( SELECT 1 FROM votes WHERE user_id = $1 AND post_id = $2)',
                [req.user.userId, post.post_id]
            );
            // if the user vote exists, set voted = true and query for what they voted for
            const voted = votes[0].exists;
            if (voted) {
                votingOptionsDictionary = post.voting_options;
                const { rows } = await pool.query(
                    'SELECT voting_option FROM votes WHERE user_id = $1 AND post_id = $2', 
                    [req.user.userId, post.post_id]
                );
                userVoteOption = rows[0].voting_option;
            }

            // i dont need voteCount here because that is calculated after the first query, this gets all the counts of the posts
            const {rows: posts } = await pool.query(
                `SELECT
                   posts.post_id,
                   COALESCE( likes.cnt, 0 ) AS like_count,
                   COALESCE( comments.cnt, 0 ) AS comment_count,
                   COALESCE( shares.cnt, 0 ) AS share_count
                 FROM posts
                 LEFT JOIN (
                   SELECT post_id, COUNT(*) AS cnt
                   FROM likes
                   GROUP BY post_id
                 ) likes ON posts.post_id = likes.post_id
                 LEFT JOIN (
                   SELECT post_id, COUNT(*) AS cnt
                   FROM comments
                   GROUP BY post_id
                 ) comments ON posts.post_id = comments.post_id
                 LEFT JOIN (
                   SELECT post_id, COUNT(*) AS cnt
                   FROM shares
                   GROUP BY post_id
                 ) shares ON posts.post_id = shares.post_id
                WHERE posts.post_id = $1`,
                [post.post_id],
              );
            const countQuery = posts[0];

            // final response once all above queries are done, i dont account for thread comments in comment count rn, later problem
            return {
                postId: post.post_id,
                userHandle: userHandle,
                userImageUrl: userImageUrl,
                postQuestion: post.post_question,
                imageUrl: post.post_image_url,
                postDescription: post.post_description,
                votingOptions: Object.keys(post.voting_options),
                voted: voted,
                userVoteOption: userVoteOption,
                liked: liked,
                votingOptionsDictionary: votingOptionsDictionary,
                voteStat: voteCount,
                likeCount: parseInt(countQuery.like_count),
                shareCount: parseInt(countQuery.share_count),
                commentCount: parseInt(countQuery.comment_count),
                createdAt: post.created_at
            };
        });
        const postData = await Promise.all(promises);
        return res.json(postData);
    }
    catch(e){
        return res.json(e)
    }
}


来源:https://stackoverflow.com/questions/65587575/multiple-queries-in-a-map-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!