首页 > 解决方案 > 如何调试挂起的承诺,而不是使用 node-postgres 解决 Postgres 查询?

问题描述

我正在使用“pg”(node-postgres)在带有 Node 应用程序的 Postgres DB 上执行一些基本的 CRUD 操作。进行此特定查询似乎有一些问题 - 整个应用程序挂起,就像 Promise 永远不会解决一样。执行在此时停止并且不会引发错误。

在我稍微更改数据库结构并重构代码(使其更加模块化等)之前,整个事情都奏效了。数据库已启动并已连接(使用 Cloud9 的 Ubuntu 14.04 LTS 容器),其他查询成功检查它是否存在。这个失败的查询('select * from inventory ...')可以正常工作 - 当我在 psql CLI 中键入它时,我得到 0 行的结果,这是应该的。所以我最好的猜测是,异步/等待逻辑中的某些东西是不正确的。

// This part executes without issues
const initDB = async () => {
    try {
        await client.connect();
        console.log('Client connected to db ...');

        const checkTable = await client.query("SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'inventory')");
        if (!checkTable.rows[0].exists) {
            const table = await client.query('CREATE TABLE inventory (prod_id serial PRIMARY KEY, product_name VARCHAR (50), category TEXT, description TEXT, price REAL, width INT, depth INT, height INT, checksum TEXT, history REAL ARRAY)');
        }
    } catch (err) {
         console.log("Error initializing db.", err);   
    }
};

// This part fails
Promise.all([getProductData(productsUrlBase)]).then(async (values) => {
       // checksum = ...
       try {
          console.log('This logs on the console');
          const check = await client.query('SELECT * FROM inventory WHERE checksum=$1', [checksum]);
          console.log(check.rows, 'if this is empty, INSERT in DB!'); // Never logs on the console. App doesn't throw error, either.
    } catch (err) {
        console.log('Query error - checking / inserting items: ', err);
    }   
});
Postgres log file:
2019-04-19 12:18:53 UTC LOG:  database system was interrupted; last known up at 2019-04-19 08:39:56 UTC
2019-04-19 12:18:54 UTC LOG:  database system was not properly shut down; automatic recovery in progress
2019-04-19 12:18:54 UTC LOG:  record with zero length at 0/17A3BF8
2019-04-19 12:18:54 UTC LOG:  redo is not required
2019-04-19 12:18:54 UTC LOG:  MultiXact member wraparound protections are now enabled
2019-04-19 12:18:54 UTC LOG:  database system is ready to accept connections
2019-04-19 12:18:54 UTC LOG:  autovacuum launcher started
2019-04-19 12:18:54 UTC LOG:  incomplete startup packet

我希望至少得到错误,但没有任何反应。您可以看到 Postgres 服务器日志——对我来说,那里似乎没有任何重大问题。

这是完整的GitHub存储库。有问题的部分在 ./data-handlers/update.js

标签: javascriptnode.jspostgresql

解决方案


您的代码中有一些小问题,但除此之外,做得很好。

1)正确返回或等待承诺:
- https://github.com/kboeff/price-checker/blob/master/app.js#L63

- https://github.com/kboeff/price-checker/blob /master/data-handlers/update.js#L12

2)通过连接node-postgres await client.connect(),再次阅读文档,这是值得的

3)循环错误=> https://github.com/kboeff/price-checker/blob/master/data-handlers/update.js#L18

4)这部分仍在for循环中,该循环旨在遍历对象属性,但应该在“for each record”循环中https://github.com/kboeff/price-checker/blob/master/data-handlers /update.js#L28-L53

5)查询中的缺失值占位符$9 https://github.com/kboeff/price-checker/blob/master/data-handlers/update.js#L36

您确定要一次触发所有这些查询吗?也许在这里同步会更好。在谈论性能时,也许您应该使用 postgres 类型的 UUID 进行校验和操作。

这是一个使用 md5 进行校验和的工作示例:

const { Client } = require('pg');
const priceAlert = require('./price-alert');
const getProductData = require('./get-product-data');
const crypto = require('crypto');

const client = new Client;

const updateDB = async (productsUrlBase, category) => {
    // connect to db
    await client.connect();
    const records = await getProductData(productsUrlBase);

    for (const record of records) {

        let checksum = '';

        for (let key in record){
            if (record.hasOwnProperty(key)) {
                if (key !== 'price') {
                    checksum += record[key] || '';
                }
            }
        }

        try {
            const md5Checksum = crypto.createHash('md5').update(checksum).digest("hex");
            const check = await client.query('SELECT * FROM inventory WHERE checksum=$1', [md5Checksum]);
            console.log(check, 'if this is empty, INSERT in DB!'); // DEBUG
            // Record not found in db, add.
            let arrLit = '{' + record.price +'}';

            if (check.rows.length === 0) {
                let rows = await client.query("INSERT INTO inventory(product_name, category, description, price, width, depth, height, checksum, history) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", [record.name, category, record.description, record.price, record.width, record.depth, record.height, md5Checksum, arrLit]);
                console.log(rows, 'INSERTED to DB.'); // DEBUG
            } else {
                // compare prices, signal for changes!
                let item = check.rows[0];
                // console.log(item);
                if (item.price !== record.price) {
                    priceAlert(item, record.price);
                    let formattedPrice = parseFloat(Math.round(record.price * 100) / 100).toFixed(2);
                    let txt = "UPDATE inventory SET price=" + formattedPrice + ", history = history||ARRAY[cast(" + formattedPrice +"as real)] WHERE checksum='" + checksum + "::uuid'";
                    let updatePrice = await client.query(txt);
                    console.log(updatePrice);

                }
            }
        } catch (err) {
            console.log('Query error - checking / inserting items: ', typeof record.price, err);
        }
    }

};

module.exports = updateDB;

列inventory.checksum 必须是UUID 类型,此示例才能正常工作
alter table inventory add column checksum uuid;

PS:也许还可以process.exit();在 app.js 第 64 行添加例如


推荐阅读