如何在Express中处理已拒绝Promise,避免应用崩溃?
问题解决:Express中未处理的Promise拒绝导致应用崩溃
核心问题
你的transferColumnAmount函数没有返回Promise。函数内部调用db.tx()后链式调用了.then()和.catch(),但没有把整个Promise链返回出去。这导致await transferColumnAmount(...)实际等待的是undefined,原Promise的拒绝状态变成了未捕获的Promise拒绝,直接绕过了你的try/catch和错误中间件,最终导致应用崩溃。
修复步骤
1. 修复数据库函数,返回Promise
删掉多余的.then(result => result)和.catch(err => throw err)(这两个逻辑完全冗余),直接返回db.tx()创建的Promise链:
const transferColumnAmount = (fromTable, toTable, fromId, toId, column, amount) => { return db.tx(t => { return t.batch([ t.one('UPDATE ${table:name} SET ${column:name} = ${column:name} + ${amount:csv} WHERE id = ${id:csv} RETURNING *', { table: fromTable, column: column, amount: -amount, id: fromId }), t.one('UPDATE ${table:name} SET ${column:name} = ${column:name} + ${amount:csv} WHERE id = ${id:csv} RETURNING *', { table: toTable, column: column, amount: amount, id: toId }) ]); }); };
2. 优化错误处理(可选)
pg-promise的t.one()在未找到匹配记录时会抛出QueryResultError,可以在错误中间件里识别这类错误,返回更贴合业务的状态码和提示:
apiRouter.use((err, req, res, next) => { // 识别pg-promise的"未找到记录"错误 if (err.name === 'QueryResultError' && err.code === 0) { err.status = 404; err.message = '指定的记录不存在'; } else if (!err.status) { err.status = 500; err.message = err.message || '服务器内部错误'; } res.status(err.status).send(err.message); });
3. 确保异步操作被完整捕获
你的transferEnvelopeBudgetByIds中间件已经用try/catch包裹了await调用,修复数据库函数返回Promise后,拒绝的Promise会被try/catch捕获,再通过next(err)传递给错误中间件,不会再出现应用崩溃的情况。
额外建议
可以把数据库函数改成async/await风格,和中间件的代码风格保持一致,可读性更强:
const transferColumnAmount = async (fromTable, toTable, fromId, toId, column, amount) => { return db.tx(async t => { const [fromResult, toResult] = await t.batch([ t.one('UPDATE ${table:name} SET ${column:name} = ${column:name} + ${amount:csv} WHERE id = ${id:csv} RETURNING *', { table: fromTable, column: column, amount: -amount, id: fromId }), t.one('UPDATE ${table:name} SET ${column:name} = ${column:name} + ${amount:csv} WHERE id = ${id:csv} RETURNING *', { table: toTable, column: column, amount: amount, id: toId }) ]); return [fromResult, toResult]; }); };
内容的提问来源于stack exchange,提问作者Brenden
相关产品推荐
相关产品推荐

