Javascript 为什么我会得到;未处理的PromisejectionWarning;?
我正在尝试调用一个异步方法。异步方法是:Javascript 为什么我会得到;未处理的PromisejectionWarning;?,javascript,node.js,async-await,Javascript,Node.js,Async Await,我正在尝试调用一个异步方法。异步方法是: async connect() { this.pool = await mysql.createPool(this.conf); await this.pool.getConnection().catch((err) => { throw new Error(err) }); } (async () => { await db.connect() .catch((err) =>
async connect() {
this.pool = await mysql.createPool(this.conf);
await this.pool.getConnection().catch((err) => { throw new Error(err) });
}
(async () => {
await db.connect()
.catch((err) => {
console.error(`Database connection error: ${err.message}`);
throw new Error(err);
});
})();
调用此方法的代码是:
async connect() {
this.pool = await mysql.createPool(this.conf);
await this.pool.getConnection().catch((err) => { throw new Error(err) });
}
(async () => {
await db.connect()
.catch((err) => {
console.error(`Database connection error: ${err.message}`);
throw new Error(err);
});
})();
但是,当this.pool.getConnection()中发生错误时,我将收到以下警告:
在阅读了类似问题的答案后,我明白拒绝承诺必须得到处理,但我不知道我在哪里没有正确处理。this.pool.getConnection()调用有一个catch块,我在其中抛出错误,以便将其传递给匿名调用函数进行处理
我在这段代码上尝试了几种变体,包括向匿名函数本身添加一个catch块并再次抛出错误,但似乎没有任何效果,并且警告总是在this.pool.getConnection()调用中发出
我试图实现的是将connect()方法中发生的任何错误传递给匿名函数来处理
我哪里做错了?提前谢谢
编辑:有趣的是,如果我按如下方式编写this.pool.getConnection()行(catch块中没有任何内容),警告就会消失:
await this.pool.getConnection().catch((err) => {});
当我尝试在arrow函数中执行任何操作时,例如将错误分配给变量,警告就会重新出现。在这段代码中,您没有处理错误:
(async () => {
await db.connect()
.catch((err) => {
console.error(`Database connection error: ${err.message}`);
throw new Error(err);
});
})();
如果db.connect()
拒绝,则将调用您的.catch()
,并重新播放。这意味着await db.connect()
将看到一个被拒绝的承诺,而包装器异步函数将返回一个被拒绝的承诺,而您没有处理程序。因此,您会收到未经处理的拒绝
您可以使错误完全在async
函数中处理,从而永远不会返回拒绝的承诺,也可以正确处理错误
仅供参考,将wait
与.catch()
混合使用也很奇怪(通常不建议这样做)。通常您会同时使用.then()
和.catch()
和等待和尝试/catch
如果您想要的所有错误处理都是记录错误并避免警告,那么您可以更改为:
db.connect().catch((err) => {
console.error(`Database connection error: ${err.message}`);
// put any other required error handling here
});
通过删除抛出错误,您可以在本地“处理”错误,因此不存在未处理的拒绝。你在这里唯一的拒绝是被处理的。另外,请注意,似乎不需要async
或wait
,因为您只是在进行函数调用并处理任何异常
请注意,以下各项的设计模式:
async function foo() {
await f();
}
与以下内容基本相同:
function foo() {
return f();
}
唯一不同的地方是如果f()
没有返回承诺或同步抛出,这两种情况在行为正确的承诺返回API中永远不会发生
因为我更喜欢实现您的目标的最简单的代码表达式,所以我不喜欢使用async/await
,除非它实际上帮助您简化代码。结果表明,尽管我的代码在任何方面都不理想,但问题的真正根源是我调用了db.connect()除了匿名函数内的其他地方。另一个调用没有用于错误处理的catch块,因此未经处理的PromiserRejection警告。一旦我删除了对db.connect()的重复调用,警告就消失了
以下是在评语/答案中贡献者帮助下改进的工作代码供参考:
数据库类中的方法:
async connect() {
this.pool = await mysql.createPool(this.conf);
return await this.pool.getConnection();
}
以及对它的呼吁:
db.connect()
.then(result => {
console.log(result)
})
.catch(err => {
console.error(`Database connection error: ${err.message}`);
});
我不知道到底是什么问题,但不要执行.catch((err)=>{throw new Error(err)})代码>,这完全没有意义。谢谢帕特里克。我(似乎有缺陷)的理解是,我需要捕获以避免收到警告,并且我需要再次抛出错误以允许调用匿名函数捕获并处理它。抛出的错误传播异步函数的方式与它们传播备份同步函数的方式非常相似。神奇之处在于关键字wait
:它将已解析的承诺转换为一个表达式,其值为已解析的结果,并将被拒绝的承诺转换为抛出的错误。谢谢,关于正确/最佳实践的一些有趣的观点。不幸的是,从db.connect()catch块中删除抛出并不能消除警告,正如我从您的回答中所理解的那样,它应该消除。我可能错了,但如果问题如您所述,我的UnhandledPromisejectionWarning不是指匿名函数,而是指这个.pool.getConnection()?@Rob-您是否100%确定使用的是我推荐的代码块中的一个,与我显示的完全一样?为了获得进一步的帮助,您必须对警告的确切来源进行故障排除。我假设它来自匿名函数返回的承诺(因为拒绝该承诺根本不被处理),但如果它也来自其他地方,您可能还需要修复其他内容。我复制了匿名函数的第一个建议表单,但堆栈跟踪已更改。我想知道真正的问题是否在我使用的mysql2模块中,因为它现在指的是/node_modules/mysql2中的文件,而不是我的任何代码。@Rob-好的,我删除了第一块代码,因为不再需要匿名函数。我无法从这里判断匿名函数是否是问题的一部分,或者它们是否在mysql2模块内部。@Rob-我注意到您在db.connect()上没有.then()
处理程序,因此您的代码无法知道连接何时成功。您确定在连接完成之前没有尝试使用连接(稍后在代码中)?