javascript - 如何调试挂起的承诺,而不是使用 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
解决方案
您的代码中有一些小问题,但除此之外,做得很好。
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 行添加例如
推荐阅读
- docker - 为两个 docker 容器设置相同的 IP 地址
- ios - UITextField 与 iOS13 中的键提供程序不兼容键值编码
- android - 在 ViewModel 中使用 viewModelScope.launch 调用挂起的方法时出现“No virtual method getTag(Ljava/lang/String;)”错误
- node.js - 如果表单没有发送两次,Promise 不想进入
- java - 创建片段时参数始终为空
- r - 为具有不同性别颜色的年龄分布创建直方图
- c - 如何访问和使用函数中获取参数为 void * 类型的单个位?
- react-native - 在创建反应应用解决方案中获取 APPLE APP SITE ASSOCIATION 时更改内容类型
- grails - Grails:如何测试关联?
- microsoft-graph-api - Microsoft Graph API:从站点默认驱动器获取所有 DriveItems:无效的 URL