Promise 的核心是可靠组合异步逻辑而非替代回调;必须显式调用 resolve/reject,链式调用需 return 值,.catch() 仅捕获前序未处理错误,async/await 仍是 Promise 语法糖。

Promise 不是用来“替代回调”的语法糖,而是把异步流程的控制权交还给开发者——它解决的不是“怎么写异步”,而是“怎么可靠地组合、中断、降级和调试异步逻辑”。
Promise 构造函数里必须执行 resolve 或 reject
常见错误是忘记调用 resolve() 或 reject(),导致 Promise 永远处于 pending 状态,后续 .then() 或 .catch() 完全不触发:
- HTTP 请求失败但没调用
reject(err),错误被静默吞掉 - 条件分支中只在 if 里
resolve(),else 里没处理,逻辑卡住 - 异步操作(如
setTimeout)未包裹在resolve()中,直接 return 值无效
正确写法示例:
new Promise((resolve, reject) => {
fetch('/api/data')
.then(res => res.json())
.then(data => resolve(data))
.catch(err => reject(new Error('Fetch failed: ' + err.message)));
});
链式调用中 return 是关键,不是自动透传
.then() 回调的返回值决定下一个 .then() 的输入;不显式 return 就等于返回 undefined,后续步骤会收到 undefined 而非你期望的数据:
立即学习“Java免费学习笔记(深入)”;
- 忘记
return fetch(...),导致下个.then()收到undefined,调用.json()报错Cannot read property 'json' of undefined - 同步计算后没
return,后续.then()拿不到加工结果 - 想抛错中断链路,却写了
throw new Error()但没return—— 实际上 throw 本身就能被下一级.catch()捕获,无需 return
典型修正:
fetch('/api/user')
.then(res => res.json()) // ← 必须 return,否则下个 then 拿不到 json 结果
.then(user => {
console.log(user.name);
return user.id; // ← 显式返回,供下个 then 使用
})
.then(id => fetch(`/api/profile/${id}`));
错误捕获不能只靠最后的 .catch()
.catch() 只能捕获它之前(链路上)未被处理的 rejection。多个并行请求、嵌套 Promise、或中间漏掉 .catch() 都会导致错误丢失:
- 用
Promise.all([p1, p2])时,任一 Promise reject 整体就 reject,但如果你没在all()后接.catch(),错误就变成 unhandled rejection -
.then(successHandler)没配.catch(),而 successHandler 内部抛错,这个错不会被外层.catch()捕获(除非你用.then(success, fail)形式) -
浏览器中未捕获的 Promise rejection 会触发
unhandledrejection事件,但 Node.js 默认直接崩溃(v15+)
稳妥做法是:每个独立异步操作后加 .catch(),或至少在链尾补上 .catch(console.error),并在开发环境监听全局事件:
window.addEventListener('unhandledrejection', event => {
console.error('Unhandled promise rejection:', event.reason);
});
async/await 不是 Promise 的替代品,而是语法糖
写 async function 本质仍是构造 Promise,所有限制和陷阱一个不少:
-
await后面如果不是 Promise,会被自动包装成Promise.resolve(value),但别因此忽略错误路径 - try/catch 能捕获 await 的 rejection,但无法捕获
setTimeout里的异步错误(除非那个 timeout 被包进 Promise) - 多个 await 串行执行,性能可能比
Promise.all()差很多;该并发的地方别傻等
例如并发获取用户和配置:
// ❌ 串行,慢 const user = await fetchUser(); const config = await fetchConfig(); // ✅ 并发,快 const [user, config] = await Promise.all([ fetchUser(), fetchConfig() ]);
真正难的从来不是“怎么写 async”,而是判断哪个环节该 reject、哪个该降级、哪个该重试、哪个该记录日志——这些决策藏在业务逻辑里,不在语法里。











