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):错误
(节点:14843)[DEP0018] DeprecationWarning:已弃用未处理的承诺拒绝。将来,未处理的承诺拒绝将以非零退出代码终止Node.js进程。
注意:我知道我可以这样解决这个问题:
foo().then(() => {}).catch(() => {});
但是我们回到回调异步风格。
我们如何解决这个问题?
答案 0 :(得分:2)
将代码包装在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)
}
}
答案 1 :(得分: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
。
答案 2 :(得分:1)
这里的每个解决方案都只会使错误消失,但您应该应该处理错误。
如何处理它取决于错误以及所处应用程序的哪一部分。以下是一些示例。
如果您正在编写节点应用程序,但会抛出一些异常,则可能要使用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)时遇到此错误,则可能意味着该应用程序有错误,但未处理。这取决于应用程序或您的输入不正确。请参阅应用程序的手册。