【问题标题】:Multiple queries in a .map function.map 函数中的多个查询
【发布时间】:2021-04-11 17:10:40
【问题描述】:
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)
    }
}

我正在尝试为每个帖子返回一个 postData 数组。出于某种原因,它继续为这些对象打印 null ,因为返回的 res.json 甚至在承诺完成之前就以某种方式运行。任何帮助表示赞赏。

我之前遇到过这个问题,使用了相同的代码,但由于某种原因它对这个问题不起作用。

【问题讨论】:

    标签: node.js postgresql promise array.prototype.map


    【解决方案1】:

    您仍然没有使用 Promise,而是将回调传递给 query。你不能从这些return 那里得到它们,Promise.all 也不会等待它们。你正在寻找

    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)
        }
    }
    

    【讨论】:

    • 非常感谢!对此,我真的非常感激!工作完美。直到现在我也不知道如何进行多行查询。我知道 + 字符串是浪费大声笑
    猜你喜欢
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 2011-04-09
    • 2018-10-16
    • 1970-01-01
    相关资源
    最近更新 更多