同步抛错能被外部catch捕获,异步抛错不能;因executor同步执行,同步throw等价于reject,而异步throw脱离Promise错误处理机制,需显式调用reject。

Promise 构造函数中传入的 executor 函数(即 new Promise(executor) 的回调)如果**同步抛出异常**,这个错误会自动被 Promise 捕获,并使该 Promise 立即变为 rejected 状态,因此可以在外部的 .catch() 中捕获。
executor 同步抛错:能被外部 catch 捕获
executor 是同步执行的。只要在它内部直接 throw(非异步代码中),Promise 就会以该错误为 reason 进入 rejected 状态。
例如:
const p = new Promise((resolve, reject) => {
throw new Error('同步错误');
});
p.catch(err => console.log(err.message)); // 输出:同步错误
等价于手动调用 reject(...),但更简洁、语义更明确。
立即学习“Java免费学习笔记(深入)”;
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
executor 异步抛错:不能被外部 catch 捕获
如果错误发生在异步任务中(如 setTimeout、fetch 回调、then 链里),此时 executor 已经执行完毕,Promise 已创建完成,再 throw 就变成未捕获的全局异常(Uncaught Error),不会进入 Promise 的 rejected 流程。
例如:
const p = new Promise((resolve) => {
setTimeout(() => {
throw new Error('异步错误'); // ❌ 不会被 p.catch 捕获
}, 0);
});
p.catch(() => console.log('这里不会执行'));
// 控制台报错:Uncaught Error: 异步错误
✅ 正确做法是在异步回调中调用 reject:
const p = new Promise((resolve, reject) => {
setTimeout(() => {
try {
throw new Error('异步错误');
} catch (e) {
reject(e); // ✅ 主动拒绝
}
}, 0);
});
p.catch(err => console.log(err.message)); // 输出:异步错误
常见误区与建议
- 不要在 executor 的异步回调里 throw —— 它脱离了 Promise 的错误处理机制
- 所有异步分支(包括
fetch、setTimeout、事件监听器等)都应显式调用resolve或reject - 若使用
async/await写 executor,需注意:async 函数返回的是 Promise,不能直接 throw 到外层 Promise;应 await 后用 try/catch 包裹并 reject - 推荐用
Promise.resolve().then(...)或Promise.reject(...)替代手写 Promise 构造器,减少 executor 错误风险
验证是否被捕获的小技巧
在浏览器或 Node.js 中,可以临时监听全局未捕获错误来排查:
// 浏览器
window.addEventListener('unhandledrejection', event => {
console.warn('未捕获的 Promise rejection:', event.reason);
});
// Node.js
process.on('unhandledRejection', (reason) => {
console.warn('未捕获的 Promise rejection:', reason);
});
如果看到日志,说明有 Promise 错误没被 .catch 处理,大概率是异步 throw 导致的。

















