猿问

为什么我会收到“UnhandledPromiseRejectionWarning”?

我正在尝试调用异步方法。异步方法是:


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() 中发生错误时,我收到以下警告:


[Thu Jun 13 2019 23:10:59] [ERROR]  (node:18296) UnhandledPromiseRejectionWarning: Error: Error: Access denied for user 'root'@'localhost' (using password: YES)

    at pool.getConnection.catch

    at process._tickCallback

[Thu Jun 13 2019 23:10:59] [ERROR]  (node:18296) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)

[Thu Jun 13 2019 23:10:59] [ERROR]  (node:18296) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

阅读了类似问题的答案后,我明白必须处理来自 Promises 的拒绝,但是我不知道我没有正确处理这个问题的地方。this.pool.getConnection() 调用有一个 catch 块,在那里我抛出错误,所以它被传递给匿名调用函数来处理。


我已经尝试了此代码的几种变体,包括向匿名函数本身添加一个 catch 块并在那里再次抛出错误,但似乎没有任何效果,并且警告总是源自 this.pool.getConnection() 调用。


我试图实现的是将 connect() 方法中发生的任何错误传递给匿名函数进行处理。


我哪里错了?提前致谢。


编辑:有趣的是,如果我按如下方式编写 this.pool.getConnection() 行(catch 块中没有任何内容),警告就会消失:


await this.pool.getConnection().catch((err) => {});

当我尝试在箭头函数内执行任何操作时,例如将错误分配给变量,警告再次出现。


三国纷争
浏览 667回答 2
2回答

慕田峪7331174

在此代码中,您没有处理错误:(async () => {    await db.connect()        .catch((err) => {            console.error(`Database connection error: ${err.message}`);            throw new Error(err);        });})();如果db.connect()拒绝,那么您的.catch()遗嘱将被调用并重新抛出。这意味着await db.connect()将看到一个被拒绝的承诺,你的包装异步函数将返回一个你没有处理程序的被拒绝的承诺。因此,您会收到未经处理的拒绝。您可以使错误完全在您的async函数中处理,因此永远不会返回被拒绝的承诺,或者您可以正确处理错误。仅供参考,await与.catch(). 通常你使用.then()and.catch()和awaitwith try/catch。如果您想要的所有错误处理都是记录错误并避免警告,那么您可以更改为:db.connect().catch((err) => {    console.error(`Database connection error: ${err.message}`);    // put any other required error handling here});通过删除throw err,您可以在本地“处理”错误,因此没有未处理的拒绝。你在这里唯一的拒绝被处理了。另外,请注意似乎不需要async或await因为您只是在进行函数调用并处理任何异常。注意,设计模式:async function foo() {    await f();}几乎与以下相同:function foo() {    return f();}唯一不同的地方是如果f()没有返回承诺或同步抛出,这两种情况都不应该在行为正确的承诺返回 API 中发生。因为我更喜欢最简单的代码表达式来实现你的目标,所以我宁愿不使用async/await它,除非它实际上可以帮助你使代码更简单。

森栏

事实证明,虽然我的代码在任何方面都不理想,但问题的真正根源是我除了匿名函数之外还从其他地方调用 db.connect() 。另一个调用没有用于错误处理的 catch 块,因此是 UnhandledPromiseRejection 警告。一旦我删除了对 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}`);  });
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答