Promise 通过链式调用和状态管理将嵌套回调扁平化,其三种状态(pending/fulfilled/rejected)不可逆,.then() 返回新 Promise 实现线性流程,需显式 return 避免链中断。

Promise 是 JavaScript 中用于处理异步操作的对象,它本身不“解决”回调地狱,而是提供了一种可链式调用、可统一错误处理的结构,让嵌套回调变成扁平化流程。
Promise 的基本形态和状态流转
一个 Promise 实例有三种状态:pending(进行中)、fulfilled(成功)、rejected(失败)。状态一旦从 pending 变为 fulfilled 或 rejected,就不可逆。
创建 Promise 时需传入一个执行器函数,它接收两个参数:resolve 和 reject —— 它们是函数,不是关键字:
const p = new Promise((resolve, reject) => {
setTimeout(() => {
const success = Math.random() > 0.5;
if (success) {
resolve('done'); // → fulfilled
} else {
reject(new Error('fail')); // → rejected
}
}, 100);
});
-
resolve(value)触发后续.then()的第一个回调 -
reject(reason)触发后续.catch()或.then(null, fn) - Promise 构造函数内部的同步错误(比如
throw new Error())会自动被转为reject
Promise 链式调用如何压平嵌套回调
传统回调地狱典型写法:
立即学习“Java免费学习笔记(深入)”;
getData(function(a) {
getMoreData(a, function(b) {
getEvenMore(b, function(c) {
console.log(c);
});
});
});
用 Promise 改写后变成线性流程:
getData() .then(a => getMoreData(a)) .then(b => getEvenMore(b)) .then(c => console.log(c)) .catch(err => console.error(err));
- 每个
.then()返回一个新的 Promise,所以能连续调用 - 如果
.then()回调返回的是普通值(如字符串、数字),它会被自动包装成Promise.resolve(value) - 如果返回的是另一个 Promise,链会等待它完成后再往下走 —— 这是实现“扁平化”的关键机制
- 任意一环抛错或
reject,都会跳过后续所有.then(),直接落到最近的.catch()
常见误用:忘记 return 导致链中断
这是最常踩的坑:在 .then() 里没显式 return,导致后续 .then() 接收到 undefined,甚至触发静默失败。
错误示例:
fetch('/api/user')
.then(res => res.json())
.then(user => {
fetch(`/api/posts?uid=${user.id}`); // ❌ 忘记 return!
})
.then(posts => console.log(posts)); // 这里拿到的是 undefined
正确写法:
fetch('/api/user')
.then(res => res.json())
.then(user => fetch(`/api/posts?uid=${user.id}`)) // ✅ 显式 return Promise
.then(res => res.json())
.then(posts => console.log(posts));
- 箭头函数单行隐式返回只适用于表达式,不适用于语句(比如
fetch(...)是调用,但没return就不算返回值) - 用
async/await能天然规避这类问题,但它底层仍依赖 Promise 链行为 - 调试时可在每个
.then()开头加console.log查看实际传入值
真正让 Promise “解耦”回调地狱的,不是语法糖,而是它强制你思考每个异步步骤的产出类型和错误传播路径。链断在哪、为什么断、谁该负责处理错误——这些在嵌套回调里是模糊的,在 Promise 链里是明确可追踪的。











