如何使用 Promise(Node、PG)设置多个嵌套查询

How to set up multiple nested queries used Promise (Node, PG)

我需要找到一种方法来为包含多个查询的嵌套查询正确设置 Promise。这是一个示例:

var results = [];

client.query("SELECT table_1_id AS id FROM table_1", (table_1_error, table_1_data) => {

    client.query("SELECT table_2_id AS id FROM table_2 WHERE table_1_id = " + table_1_data.rows[0].id, (table_2_error, table_2_data) => {

        table_2_data.rows.forEach(function(table_2_row) {

            client.query("SELECT table_3_id AS id FROM table_3_id WHERE table_2_id = " + table_2_row.id, (table_3_error, table_3_data) => {

                table_3_data.rows.forEach(function(table_3_row) {

                    client.query("SELECT table_4_id AS id FROM table_4_id WHERE table_3_id = " + table_3_row.id, (table_4_error, table_4_data) => {

                        results.push({"table_1_id": table_1_data.rows[0].id, "table_2_id": table_2_row.id, "table_3_id": table_3_row.id, "table_4_id": table_4_row.id});

                    });

                });

             });

        });

    });

});

//code below needs to wait until the above is complete

我正在使用 PG 节点模块来执行这些查询。

由于 PG 直接支持 promises,你可以使用 promises 和 async/await 这样做:

async function getResults() {
    let results = [];
    let table_1_data = await client.query("SELECT table_1_id AS id FROM table_1");
    let table_2_data = await client.query("SELECT table_2_id AS id FROM table_2 WHERE table_1_id = " + table_1_data.rows[0].id);
    for (let table_2_row of table_2_data.rows) {
        let table_3_data = await client.query("SELECT table_3_id AS id FROM table_3_id WHERE table_2_id = " + table_2_row.id);
        for (let table_3_row of table_3_data.rows) {
            let table_4_data = client.query("SELECT table_4_id AS id FROM table_4_id WHERE table_3_id = " + table_3_row.id);
            results.push({
                "table_1_id": table_1_data.rows[0].id,
                "table_2_id": table_2_row.id,
                "table_3_id": table_3_row.id,
                "table_4_id": table_4_data.id
            });
        }
    }
    return results;
}

getResults().then(results => {
    // process results here
    console.log(results);
}).catch(err => {
    // process error here
    console.log(err);
});

请注意,与 node.js 中的所有异步操作一样,getResults() 在完成之前不会阻塞(它立即 returns 一个承诺)所以你必须在 getResults() 中处理结果=13=]回调。


注意:像这样的大量嵌套多步请求意味着可能建议对数据库中的数据进行更好的结构化或在一个查询中执行多个步骤的查询。

注意:您的代码(看起来可能是伪代码)在将结果推入数组时引用了 table_4_row.id,但您的代码中没有名为 table_4_row 的变量。我假设你的意思是 table_4_data.id,但你必须将其修复为它应该是的任何内容。

注意:此结构假定您希望在出现任何错误时中止操作,并且它将拒绝出现该错误的承诺。如果您想要不同的内部错误处理(例如跳过或忽略错误),则必须定义您想要的内容。您可以使用 try/catch 捕获来自 await 的错误以引入自定义错误处理。