我一直在努力寻找正确的模式来处理嵌套的await / async例程中的错误,同时还要保持代码的简洁和简洁。 (尽管阅读了无数的文章和博客)
我有一组(从根本上)类似于以下功能的功能:
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)
答案 0 :(得分:0)
您总是可以让拒绝冒出气泡,并选择最佳级别来捕获它们:
async function f1() { return await f2(); }
async function f2() { return await f3(); }
async function f3() {
return Promise.reject('no way!');
// or
throw 'no way!';
}
async function f_await() {
try {
console.log('never succeeds here', await f1());
} catch (err) {
console.log('I check for errors at the level I prefer!');
throw 'I can even intercept and rethrow!';
}
return 'or i can keep going like eveything is fine';
}
function f_then() {
f1().then(console.log.bind(null, 'never succeeds here'))
.catch(function (err) {
console.log('I check for errors at the level I prefer!');
throw 'I can even intercept and rethrow!';
}).then(function () {
return 'or i can keep going like eveything is fine';
});
}
如果您触发未处理的拒绝警告,那是因为...您在链中的任何点都没有处理某些拒绝,而您始终需要:即使在同步代码中,如果引发了异常且从未捕获到异常,电脑会告诉您它有多不快乐。
如果您认为处理代码中被拒绝的SQL查询的最佳方法是在validate
中,那么就去吧:用await
/ {{将这个try
括起来1}}以您认为最佳的方式{@ {1}}阻止并“处理”错误...不确定我在这里看到了问题!