【发布时间】:2019-02-03 14:19:42
【问题描述】:
我正在努力弄清楚在嵌套等待/异步例程中处理错误的正确模式是什么,同时又要保持代码简洁明了。 (尽管阅读了无数的文章和博客)
我有一组(基本上)类似于以下的函数:
async validate(params) {
const recCount = await this._getCount(db, params);
if( recCount > 0 )
return "Record already exists";
}
_getCount 是创建 sql 的包装器
async _getCount(conn, regdata) {
const sql = "SELECT count(*) AS 'count' FROM myTable WHERE product = ? and category = ?";
let rows = await this._execSQL(conn, sql, [ regdata.product, regdata.category ]);
return rows[0].count;
}
实际查询执行如下:
async _execSQL(conn, sql, data) {
const [ rows ] = await conn.query(sql, data);
return rows;
}
如果查询失败,方法 conn.query(来自 mysql2/promise 库)将拒绝承诺。
所以,我的问题变成了处理异常的正确模式是什么?
在同步世界中,我对 _execSQL 和 _getCount 无能为力,只能在 validate 中捕获异常;只是自然地让异常冒泡。
但是,在异步世界中,我如何在不出现“未处理的承诺”异常的情况下进行等效操作?
我是否坚持必须在每个异步例程中一直捕获错误?
或者有没有更好的方法而不使用像 process.on('unhandledRejection',...) 这样的东西,感觉就像我在规避问题?
编辑:添加示例和堆栈跟踪
好的,所以我实际上已将此代码添加到我的应用程序中,并将 try/catch 放入 validate 函数中。逐字代码是:
async validate(db, params) {
let recCount;
try {
recCount = await this._getCount(db, params);
} catch (err) {
console.log('Caught error', err);
}
if (recCount > 0) return 'Record already exists';
}
async _getCount(conn, regdata) {
const sql = "SELECT count(*) AS 'count' FROM myTable WHERE product = ? and category = ?";
let rows = await this._execSQL(conn, sql, [ regdata.product, regdata.category ]);
return rows[0].count;
}
async _execSQL(conn, sql, data) {
const [ rows ] = await conn.query(sql, data);
return rows;
}
我有一个用于 unhandledRejection 的事件处理程序,它会报告事件以及内部异常以及堆栈跟踪。这是它转储出来的:
Stack Trace:
AppError: Unhandled promise rejection. Plugin may not be properly handling error.
at process.on (D:\Development\website\service\server.js:73:5)
at emitTwo (events.js:126:13)
at process.emit (events.js:214:7)
at emitPendingUnhandledRejections (internal/process/promises.js:108:22)
at process._tickCallback (internal/process/next_tick.js:189:7)
Inner Error:
{ "message": "connect ECONNREFUSED 127.0.0.1:3306", "code": "ECONNREFUSED", "errno": "ECONNREFUSED" }
Error: connect ECONNREFUSED 127.0.0.1:3306
at PromisePool.query (D:\Development\website\webhooks\node_modules\mysql2\promise.js:323:22)
at Registration._execSQL (D:\Development\website\webhooks\plugins\registration.js:108:31)
at Registration._logRequest (D:\Development\website\webhooks\plugins\registration.js:179:14)
at Registration.register (D:\Development\website\webhooks\plugins\registration.js:52:8)
at Router.exec (D:\Development\website\service\router.js:119:20)
at IncomingMessage.request.on (D:\Development\website\service\server.js:292:47)
at emitNone (events.js:106:13)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
【问题讨论】:
-
万一有人落入了让我在这里停留了一段时间的陷阱,我无意中没有在之前的操作中添加
await(_logRequest) 并且没有这样做它跑进去了与_getCount平行。两者最终都抛出了一个错误,但只有一个被捕获。放入此示例代码有助于定位问题。所以....经验教训....确保你await所有你想以串行方式运行的异步函数。
标签: node.js async-await node-mysql2