Promise 用于组织异步依赖而非简化流程;then 链明确执行顺序而非仅减少嵌套;滥用致错误静默、调试困难;async/await 是语法糖,底层仍依赖 Promise;需依数据依赖关系选择 await、Promise.all 或 allSettled。

Promise 不是用来“简化”异步流程的,而是用来“组织”和“表达”异步依赖关系的——用错方式反而会让代码更难懂。
Promise.then() 链式调用不是为了减少嵌套,而是为了明确执行顺序
很多人以为 then() 是为了解决回调地狱(callback hell),但实际中滥用链式调用会导致错误被静默吞掉、调试困难、逻辑分支混乱。
- 每个
then()只接收上一个成功返回的值,失败不会自动向下传递,除非显式return Promise.reject(...)或抛出异常 - 如果某个
then()里忘记return,后续then()会收到undefined,而非预期数据 - 多个并行请求不要强行塞进一条链,该用
Promise.all([p1, p2])就别写p1.then(() => p2)
async/await 是 Promise 的语法糖,不是替代品
async/await 看起来更“同步”,但底层完全依赖 Promise。它解决的是书写形式问题,不改变异步本质。
-
await只能用在async函数内,否则报错SyntaxError: await is only valid in async functions -
await后面如果不是 Promise,会被自动包装成Promise.resolve(value),这点常被忽略导致时序误判 - 想捕获错误必须用
try/catch,而不是靠.catch(),二者作用域不同
Promise.race() 和 Promise.allSettled() 容易用反
这两个方法名字相似,行为却相反:一个看“谁最快”,一个看“谁全结束”。选错会直接导致业务逻辑出错。
立即学习“Java免费学习笔记(深入)”;
-
Promise.race([p1, p2])在任一 Promise settle(fulfill 或 reject)时就结束,哪怕那个是失败的 —— 常见于超时控制,但若没处理 reject,就会抛未捕获异常 -
Promise.allSettled([p1, p2])总是等待全部完成,返回每个 Promise 的状态对象({status: 'fulfilled', value}或{status: 'rejected', reason}),适合“不管成败都要汇总结果”的场景 -
Promise.all()一旦有任意一个 reject 就立刻 reject,适合“全成功才继续”的原子操作,比如批量提交表单
reject 不等于 throw,catch 也不等于 try/catch
Promise 构造函数里的 throw 会被自动转为 reject,但普通同步错误(如访问 undefined.x)不会自动进入 .catch(),除非发生在 Promise 执行器或 then() 回调中。
- 构造 Promise 时,
new Promise((resolve, reject) => { throw new Error('oops') })等价于reject(new Error('oops')) - 但在
then()外部抛错(比如console.log(x.y); then(...)),这个错误跟 Promise 链无关,.catch()捕不到 -
浏览器中未被
catch()的 Promise rejection 会触发unhandledrejection事件,Node.js 则直接退出进程(v15+)
真正难的从来不是怎么写 Promise,而是判断哪一步该用 await、哪一步该用 Promise.all、哪一步根本不该封装成 Promise —— 这些取决于你对数据依赖关系的真实理解,而不是语法是否“看起来简洁”。











