使用node-pg插入Postgres数据时如何处理报错避免应用崩溃
问题原因
该报错触发原因是workorders表的wo_id字段为主键,主键自带唯一非空约束,你提交的wo_num值已经存在于表中,触发了唯一约束校验失败。同时你的代码没有捕获异步操作抛出的异常,Node.js 环境中未处理的 Promise 拒绝会直接导致进程退出,表现为整个应用崩溃。
解决步骤
- 第一步:给异步操作链添加错误捕获逻辑,所有数据库操作的异常都在捕获块中处理,返回对应提示给前端,避免异常冒泡到进程层面。
- 第二步:如果业务逻辑支持同个工单下新增多个明细、不需要重复创建工单,可以修改插入工单的SQL语句,使用PostgreSQL原生的
ON CONFLICT语法处理主键冲突,从根源避免该报错。
PostgreSQL中唯一约束冲突的错误码固定为23505,可以通过错误码判断错误类型,返回更精准的用户提示。
修改后的代码示例
const insertLineItemDB = (request, response) => { const { wo_num, description, due_date, cost } = request.body // 新增ON CONFLICT逻辑,主键冲突时跳过插入,不抛出错误 const query1 = 'INSERT INTO workorders (wo_id, due_date, complete) VALUES ($1, $2, 0) ON CONFLICT (wo_id) DO NOTHING;'; const query2 = 'INSERT INTO lineitems (wo_num, description, cost) VALUES ($1, $2, $3);'; Promise.all([ pool.query(query1, [wo_num, due_date]), pool.query(query2, [wo_num, description, cost]) ]).then(function([query1Results, query2Results]) { response.status(201).send('Successfully inserted'); }).catch(err => { // 捕获所有异常,避免进程崩溃 console.error(err); if (err.code === '23505') { response.status(400).send('当前工单编号已存在,请勿重复提交'); } else { response.status(500).send('服务器内部错误,请稍后重试'); } }) }
如果你不需要冲突时跳过插入,也可以保留原SQL语句,只保留catch块的错误处理逻辑,同样可以避免应用崩溃,只给用户返回对应提示。
内容的提问来源于stack exchange,提问作者NicLovin
相关产品推荐
相关产品推荐

