使用async/await冒泡和捕获异常的正确模式是什么



我很难理解在嵌套的等待/异步例程中处理错误的正确模式是什么,同时保持代码简洁明了。(尽管阅读了无数文章和博客)

我有一组功能(基本上)类似于以下内容:

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库)将拒绝promise。

因此,我的问题变成了处理异常的正确模式是什么?

在同步世界中,我对_execSQL_getCount都无能为力,只能在validate中捕获异常;只是自然地让例外出现。

然而,在异步世界中,如何在不出现"未处理的Promise"异常的情况下执行等效操作?

我是不是一直要在各个级别的每个异步例程中捕捉错误?

或者有没有更好的方法不使用像process.on('unhandledRejection',...)这样的东西,感觉我在规避这个问题?

EDIT:添加了示例和堆栈跟踪

好的,所以我实际上已经将这段代码添加到我的应用程序中,并将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:Developmentwebsiteserviceserver.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:Developmentwebsitewebhooksnode_modulesmysql2promise.js:323:22)
at Registration._execSQL (D:Developmentwebsitewebhookspluginsregistration.js:108:31)
at Registration._logRequest (D:Developmentwebsitewebhookspluginsregistration.js:179:14)
at Registration.register (D:Developmentwebsitewebhookspluginsregistration.js:52:8)
at Router.exec (D:Developmentwebsiteservicerouter.js:119:20)
at IncomingMessage.request.on (D:Developmentwebsiteserviceserver.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)

您可以随时让拒绝冒出来,并选择最佳级别来捕捉它们:

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中,那么就去做吧:用try/catch块包围这个await,并以您认为最好的方式"处理"catch中的错误。。。我不确定我看到了这里的问题!

相关内容

  • 没有找到相关文章

最新更新