当 Promise 被 reject 且未处理时,浏览器会显示 "Uncaught (in promise)" 错误。
本文介绍了三种常见未处理情况:
- 直接 reject
- async 函数抛出错误
- then 链中未捕获的错误
提供了四种处理方法:
- 使用 .catch()
- try...catch
- Promise 构造函数内部捕获
- 全局事件监听(unhandledrejection)
最佳实践建议始终为 Promise 添加错误处理,包括使用空 catch 处理不关心的结果,以及使用 Promise.allSettled 处理并行操作。
这些方法能有效防止应用因未处理的 Promise 错误而崩溃,同时改善调试体验。
关联阅读推荐
JavaScript Promise 总结(附:常见返回 Promise 的API,ServiceWorker 中 Promise)
Promise 未捕获 reject 错误处理指南
当 Promise 被 reject 且没有相应的错误处理时,浏览器控制台确实会显示警告/错误。
具体表现
在 Chrome DevTools 中,你会看到类似这样的错误:
Uncaught (in promise) Error: Something went wrong
at <anonymous>:1:20
为什么会出现这个警告?
Promise 的设计哲学是:每个 reject 都应该被处理。
如果 reject 没有被捕获,JavaScript 引擎认为这可能是一个未被注意的错误。
示例代码
javascript
// 情况1:直接 reject 没有被处理
const promise1 = new Promise((resolve, reject) => {
reject(new Error('Something went wrong'));
});
// 控制台会显示:Uncaught (in promise) Error: Something went wrong
// 情况2:async 函数中 throw 没有被捕获
async function failedAsync() {
throw new Error('Async error');
}
failedAsync(); // 同样会显示未捕获的 promise 错误
// 情况3:then 链中的 reject 没有被后续的 catch 处理
Promise.resolve()
.then(() => {
throw new Error('Error in then');
});
// 这里虽然看起来有 then,但没有 catch,所以错误仍未被捕获
如何正确处理?
1. 使用 .catch()
javascript
promise
.then(result => {
// 处理成功情况
})
.catch(error => {
// 处理 reject 和 then 中抛出的错误
console.error('Caught error:', error);
});
2. 使用 try...catch 处理 async/await
javascript
async function handleAsync() {
try {
await someAsyncFunction();
} catch (error) {
console.error('Caught error:', error);
}
}
3. 在 Promise 构造函数中捕获错误
javascript
const safePromise = new Promise((resolve, reject) => {
try {
// 可能出错的代码
const result = riskyOperation();
resolve(result);
} catch (error) {
reject(error);
}
});
4. 全局捕获未处理的 Promise 错误
javascript
// 在浏览器中
window.addEventListener('unhandledrejection', event => {
console.warn('未处理的 Promise 拒绝:', event.reason);
event.preventDefault(); // 阻止默认的控制台错误
});
// 在 Node.js 中
process.on('unhandledRejection', (reason, promise) => {
console.log('未处理的拒绝:', reason);
});
最佳实践建议
-
总是为 Promise 链添加错误处理
-
在 async 函数中总是使用 try...catch
-
对于不关心结果的 Promise,至少加上一个空的 catch
javascriptsomeAsyncOperation().catch(() => {}); -
对于可能失败的多个并行操作,使用
Promise.allSettledjavascriptconst results = await Promise.allSettled(promises); results.forEach(result => { if (result.status === 'rejected') { console.log('失败:', result.reason); } });
这样可以确保你的应用不会因为未处理的 Promise 错误而崩溃,同时也能获得更好的调试体验。