异步等待承诺上的 UnhandledPromiseRejectionWarning
Posted
技术标签:
【中文标题】异步等待承诺上的 UnhandledPromiseRejectionWarning【英文标题】:UnhandledPromiseRejectionWarning on async await promise 【发布时间】:2019-03-19 13:18:33 【问题描述】:UnhandledPromiseRejectionWarning
异步等待承诺
我有这个代码:
function foo()
return new Promise((resolve, reject) =>
db.foo.findOne(, (err, docs) =>
if (err || !docs) return reject();
return resolve();
);
);
async function foobar()
await foo() ? console.log("Have foo") : console.log("Not have foo");
foobar();
结果:
(节点:14843)UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝 id:1):false
(node:14843) [DEP0018] DeprecationWarning:不推荐使用未处理的承诺拒绝。将来,未处理的 Promise 拒绝将使用非零退出代码终止 Node.js 进程。
注意:我知道我可以这样解决这个问题:
foo().then(() => ).catch(() => );
然后我们“回到”回调异步样式。
我们如何解决这个问题?
【问题讨论】:
db.foo
是什么?是猫鼬吗?
@estus 不,它是 MongoJS,见这里github.com/mafintosh/mongojs
async/await
需要 try/catch
。如果你想用 async/await 风格编写这些代码,你可以试试util.promisify
,它处理遵循错误优先回调风格的函数。
你觉得foo().catch(console.error)
有什么问题?
【参考方案1】:
将您的代码包装在try-catch
块中。
async function foobar()
try
await foo() ? console.log("Have foo") : console.log("Not have foo");
catch(e)
console.log('Catch an error: ', e)
【讨论】:
我正在使用异步等待来减少不必要的代码。 Try 和 catch 块真的不是这里的目标 - 我可以只使用上面提到的常规回调。 @Raz 错误处理不是“不必要的”。你会认为try..catch
在同步代码中是不必要的吗? async
也是如此。
@Raz async/await
是一种语法糖,可让您编写看起来像同步的代码。您如何处理同步代码中的错误? --> try/catch
。首先,它根本不是为了减少代码(即使情况经常如此)
@Raz,我希望你 @estues 和 @Kristianmitk 解决了你的问题。此外,节点只提供warning
,如果您不关心错误处理,那么您也可以忽略警告,但我强烈建议不要这样做。为运行时错误添加适当的处理只是一个好习惯。
async await 后面应该跟一个 promise 吗?我可以删除承诺并在 foo 函数中返回 true
或 false
吗?我试过了,还是不行。【参考方案2】:
then(() => ).catch(() => )
不需要,因为catch
不一定应该在then
之后。
UnhandledPromiseRejectionWarning
表示承诺没有与catch
同步链接,这导致未处理的拒绝。
在async..await
中,应使用try..catch
捕获错误:
async function foobar()
try
await foo() ? console.log("Have foo") : console.log("Not have foo");
catch (error)
console.error(error);
另一种方法是在顶层处理错误。如果foobar
是应用程序入口点并且不应该被链接到其他任何地方,那么它是:
foobar().catch(console.error);
foo
的问题在于它没有提供有意义的错误。最好应该是:
if (err || !docs) return reject(err);
此外,大多数流行的基于回调的库都承诺避免使用new Promise
。 mongoist
为 mongojs
。
【讨论】:
【参考方案3】:这里的每个解决方案都只是消除错误,但您可能应该处理错误。
您如何处理它取决于错误以及您所在的应用程序的哪个部分。以下是一些示例。
你正在编写一个应用程序
如果您正在编写节点应用程序并抛出异常,您可能希望使用process.exit(1)
退出应用程序并向用户显示错误:
async function init()
await doSomethingSerious();
init().catch(error =>
console.error(error);
process.exit(1)
);
你正在编写一个模块
如果代码预期错误,您可以捕获它并将其用作值:
module.exports = async function doesPageExist(page)
try
await fetchPage(page);
return true;
catch (error)
if (error.message === '404')
return false;
// Unrecognized error, throw it again
throw error;
请注意,当错误不是预期的错误时,此示例会重新引发错误。 这很好。处理网络错误是最终用户的责任:
const doesPageExist = require('my-wonderful-page-checker');
async function init()
if (await doesPageExist('https://example.com/nope'))
console.log('All good')
else
console.log('Page is missing ?')
// Just like before
init().catch(error =>
console.error(error);
process.exit(1)
);
你是用户
如果您在通过命令行(如 webpack 或 babel)使用预打包的应用程序时看到此错误,这可能意味着该应用程序有错误但未处理。这取决于应用程序或您的输入不正确。请参阅应用程序手册。
【讨论】:
以上是关于异步等待承诺上的 UnhandledPromiseRejectionWarning的主要内容,如果未能解决你的问题,请参考以下文章