Promise是组织异步状态流的工具,非同步化手段;仅当包装无Promise接口的异步操作(如setTimeout)时需new Promise;对fetch等原生Promise API再封装会破坏错误传播。

Promise 不是“让异步变同步”的工具,而是把异步操作的处理逻辑显式地组织成链式、可捕获的状态流。 它不会消除异步性,但能避免回调地狱,统一错误处理路径。
Promise 构造函数怎么写?什么时候必须 new Promise?
只有当你需要把一个**没有 Promise 接口的异步操作**(比如 setTimeout、XMLHttpRequest、某些老库的回调函数)包装成 Promise 时,才需要手动 new Promise。
常见错误是:对已返回 Promise 的 API(如 fetch()、axios.get())再包一层 new Promise,这不仅多余,还容易破坏原生 Promise 的错误传播和取消能力。
- ✅ 正确:包装原生回调 API
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
- ❌ 错误:给 fetch 多套一层
// 别这么写
fetch('/api/data')
.then(() => new Promise(resolve => resolve('done'))); // 无意义嵌套
then() 和 catch() 的执行时机与错误穿透规则
then() 接收两个参数:onFulfilled 和 onRejected;但更推荐只传第一个,用单独的 catch() 统一处理错误——因为后者会捕获前面所有 then() 中抛出的异常,包括 onFulfilled 内部的 throw 或运行时错误。
立即学习“Java免费学习笔记(深入)”;
大小仅1兆左右 ,足够轻便的商城系统; 易部署,上传空间即可用,安全,稳定; 容易操作,登陆后台就可设置装饰网站; 并且使用异步技术处理网站数据,表现更具美感。 前台呈现页面,兼容主流浏览器,DIV+CSS页面设计; 如果您有一定的网页设计基础,还可以进行简易的样式修改,二次开发, 发布新样式,调整网站结构,只需修改css目录中的css.css文件即可。 商城网站完全独立,网站源码随时可供您下载
-
catch()等价于then(null, onRejected) - 只要链中任意环节没被
catch()拦截,错误会一直向后传递,直到遇到第一个catch()或被全局未处理拒绝(unhandledrejection)捕获 -
then(onFulfilled)内部若throw,后续then()不会执行,但下一个catch()会收到这个错误
Promise.resolve(1)
.then(x => { throw new Error('boom'); })
.then(x => console.log('never runs'))
.catch(err => console.error(err.message)); // 输出 'boom'
async/await 是语法糖,但它改变了错误处理习惯
async/await 底层仍是 Promise,但写法上更接近同步代码。关键区别在于:await 后面如果是一个 rejected Promise,会直接抛出错误,必须用 try/catch 捕获,不能靠链式 catch()。
- 不加
try/catch的await出错 = 未捕获的 Promise rejection -
await Promise.reject('err')和throw 'err'在try/catch中行为一致 - 多个
await串行执行时,前一个失败,后续不会执行;想并行就用Promise.all([p1, p2])
async function fetchUser() {
try {
const res = await fetch('/api/user');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.error('Fetch failed:', err);
throw err; // 如果上层还要处理,记得 re-throw
}
}
Promise.all() 和 Promise.race() 容易忽略的细节
Promise.all() 要求所有子 Promise 都 fulfilled 才算成功;只要一个 rejected,整个就 rejected —— 即使其他都已完成。如果你需要“不管成败都等全部结束”,得用 Promise.allSettled()。
Promise.race() 返回第一个 settled(fulfilled 或 rejected)的结果,不是第一个 fulfilled。这点常被误解。
-
Promise.race([Promise.reject('a'), Promise.resolve('b')])→ 立即 rejected,值为'a','b'被丢弃 -
Promise.any()是新标准(ES2021),返回第一个 fulfilled,全 rejected 才 rejected(带AggregateError) - 所有这些静态方法都不改变原始 Promise 的状态,只是组合逻辑
const p1 = new Promise(r => setTimeout(() => r('one'), 100));
const p2 = Promise.reject('two');
Promise.race([p1, p2]).catch(console.error); // 输出 'two'
真正难的不是写 then 或 await,而是判断某个异步操作是否该被 cancel、是否要设置超时、失败后要不要重试——这些逻辑不在 Promise 原语里,得靠 AbortController、Promise.race() 包裹或自定义封装来补足。









