【问题标题】:Promise.all and .map returning nullPromise.all 和 .map 返回 null
【发布时间】:2021-04-11 14:35:58
【问题描述】:
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);
    })
}

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

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

【问题讨论】:

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


【解决方案1】:

多个问题:

  • return postObjectbefore userVoteOption is assigned
  • 你实际上并没有use promises with node-postgres
  • ...因此map 回调的返回值不是一个承诺
  • 你从不初始化postObject
  • 您将函数标记为async,但从未使用await
  • 您单独处理循环中的每个错误(这会导致res.json 在出现多个错误时被多次调用)

要解决这些问题,请使用

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

此外,您实际上根本不应该在这里使用循环。一次从 postgres 查询多行!使用this approach 提供ID:

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

【讨论】:

  • 感谢您的帮助。我做了一些删除并输入堆栈,所以有些事情搞砸了。我的主要目标是弄清楚为什么 null 被打印出来,我看看你是怎么做的“const postData = await Promise.all(promises); res.json(postData);”但我仍然无法让它工作。我没有在此处发布的函数中有很多嵌套查询。会不会跟这个有关系?
  • 当然可能与此有关……您可以edit your question 来更新您实际代码中的小东西,但如果有很大的不同,您最好是ask a new question
  • 一般来说,不要做很多嵌套查询。使用 SQL 连接以获得更好的性能。
  • 我将代码编辑为我目前拥有的全部功能。是的,我是 sql 的新手,我父亲告诉我同样的事情。从 firestore 转移到 postgres 有点不同,哈哈。感谢您的帮助!
  • 您还没有将pool.query 调用转换为使用promise 而不是回调,以便您可以按顺序await 它们。
猜你喜欢
  • 1970-01-01
  • 2019-05-08
  • 2018-05-11
  • 2017-02-26
  • 2020-11-05
  • 2020-08-06
  • 2012-08-08
  • 1970-01-01
  • 2018-02-20
相关资源
最近更新 更多