Почему я получаю "UnhandledPromiseRejectionWarning"? - PullRequest
1 голос
/ 14 июня 2019

Я пытаюсь вызвать асинхронный метод.Асинхронный метод:

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.

Прочитав ответы на подобные вопросы, я понимаю, что отклонения от Обещаний должны быть обработаны, но я заблудился относительно того, где я не правильно обработал это.Вызов this.pool.getConnection () имеет блок catch, и там я выкидываю ошибку, чтобы передать ее анонимной вызывающей функции для обработки.

Я пробовал несколько вариантов этого кода,включая добавление блока catch к самой анонимной функции и повторное появление ошибки там, но, похоже, ничего не работает, и предупреждение всегда возникает при вызове this.pool.getConnection ().

Чего я пытаюсь достичьдля любой ошибки, возникающей в методе connect (), передаваемой анонимной функции для обработки.

Куда я иду неправильно?Заранее спасибо.

Редактировать: интересно, если я напишу строку this.pool.getConnection () следующим образом (в блоке catch ничего нет), предупреждение исчезнет:

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

В тот момент, когда я пытаюсь что-то сделать внутри функции стрелки, например, присвоить ошибку переменной, всплывающее предупреждение.

Ответы [ 2 ]

1 голос
/ 14 июня 2019

В этом коде вы не обрабатываете ошибку:

(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() и .catch() вместе и await с 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, за исключением случаев, когда это действительно помогает вам сделать код проще.

0 голосов
/ 14 июня 2019

Оказывается, что хотя мой код ни в коем случае не был идеальным, истинный источник проблемы заключался в том, что я вызывал 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}`);
  });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...