Promise 的核心是可靠组合异步逻辑而非替代回调;必须显式调用 resolve/reject,链式调用需 return 值,.catch() 仅捕获前序未处理错误,async/await 仍是 Promise 语法糖。
Promise 不是用来“替代回调”的语法糖,而是把异步流程的控制权交还给开发者——它解决的不是“怎么写异步”,而是“怎么可靠地组合、中断、降级和调试异步逻辑”。
常见错误是忘记调用 resolve() 或 reject(),导致 Promise 永远处于 pending 状态,后续 .then()

.catch() 完全不触发:
reject(err),错误被静默吞掉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)));
});
.then() 回调的返回值决定下一个 .then() 的输入;不显式 return 就等于返回 undefined,后续步骤会收到 undefined 而非你期望的数据:
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() 只能捕获它之前(链路上)未被处理的 rejection。多个并行请求、嵌套 Promise、或中间漏掉 .catch() 都会导致错误丢失:
Promise.all([p1, p2]) 时,任一 Promise reject 整体就 reject,但如果你没在 all() 后接 .catch(),错误就变成 unhandled rejection.then(successHandler) 没配 .catch(),而 successHandler 内部抛错,这个错不会被外层 .catch() 捕获(除非你用 .then(success, fail) 形式)unhandledrejection 事件,但 Node.js 默认直接崩溃(v15+)稳妥做法是:每个独立异步操作后加 .catch(),或至少在链尾补上 .catch(console.error),并在开发环境监听全局事件:
window.addEventListener('unhandledrejection', event => {
console.error('Unhandled promise rejection:', event.reason);
});
写 async function 本质仍是构造 Promise,所有限制和陷阱一个不少:
await 后面如果不是 Promise,会被自动包装成 Promise.resolve(value),但别因此忽略错误路径setTimeout 里的异步错误(除非那个 timeout 被包进 Promise)Promise.all() 差很多;该并发的地方别傻等例如并发获取用户和配置:
// ❌ 串行,慢 const user = await fetchUser(); const config = await fetchConfig(); // ✅ 并发,快 const [user, config] = await Promise.all([ fetchUser(), fetchConfig() ]);
真正难的从来不是“怎么写 async”,而是判断哪个环节该 reject、哪个该降级、哪个该重试、哪个该记录日志——这些决策藏在业务逻辑里,不在语法里。