Promise 解决过程是 Promise A+ 规范的核心机制,用于处理 then 回调返回值与 Promise 状态的关系。以下从规范角度结合代码示例解析这一过程。
一、解决过程的核心定义
Promise 解决过程是一个抽象操作 [[Resolve]](promise, x),表示将 promise 的状态与值根据 x 的类型和状态进行解析。其核心逻辑是:若 x 是 Promise 或 Thenable(具有 then 方法),则使 promise 接受 x 的状态;否则用 x 的值完成 promise。
二、解决过程的具体规则
1. x 与 promise 为同一对象
-
规则 :若
promise和x指向同一实例,以TypeError拒绝promise,避免循环引用。 -
示例 :
javascriptconst promise = new Promise(resolve => { resolve(promise); // promise 和 x 为同一对象 }); promise.then( value => console.log('成功'), reason => console.log('错误:', reason) // 输出:错误: TypeError );
2. x 是 Promise 实例
-
规则 :
- 若
x处于pending,promise保持pending,直至x状态确定。 - 若
x处于fulfilled,promise以相同值fulfilled。 - 若
x处于rejected,promise以相同原因rejected。
- 若
-
示例 :
javascriptfunction createPromise(delay, value) { return new Promise(resolve => { setTimeout(() => resolve(value), delay); }); } const p1 = createPromise(100, 'p1 resolved'); const p2 = new Promise(resolve => { resolve(p1); // x 是 Promise }); p2.then( value => console.log('p2 结果:', value), // 输出:p2 结果: p1 resolved reason => console.log('p2 错误:', reason) );
3. x 是 Object 或 Function(Thenable)
-
规则 :
- 尝试获取
x.then,若获取时抛出异常e,则以e拒绝promise。 - 若
then是函数,调用x.then(resolvePromise, rejectPromise),其中:resolvePromise(y):递归执行[[Resolve]](promise, y)。rejectPromise(r):以r拒绝promise。- 若
resolvePromise和rejectPromise被多次调用,仅首次有效。
- 若调用
then时抛出异常e,且resolvePromise/rejectPromise未被调用,则以e拒绝promise。 - 若
then不是函数,以x完成promise。
- 尝试获取
-
示例 :
javascript// 定义 Thenable 对象 const thenable = { then(resolve, reject) { console.log('调用 then 方法'); setTimeout(() => { resolve('thenable value'); // 调用 resolvePromise }, 500); } }; const promise = new Promise(resolve => { resolve(thenable); // x 是 Thenable }); promise.then( value => console.log('结果:', value), // 输出:结果: thenable value reason => console.log('错误:', reason) );
4. x 是普通值(非对象、非函数)
-
规则 :以
x直接完成promise。 -
示例 :
javascriptconst promise = new Promise(resolve => { resolve(42); // x 是普通值 }); promise.then( value => console.log('普通值结果:', value), // 输出:普通值结果: 42 reason => console.log('错误:', reason) );
三、解决过程在链式调用中的体现
javascript
function promise1() {
return new Promise(resolve => {
setTimeout(() => {
console.log('promise1 完成');
resolve('p1 value');
}, 1000);
});
}
function promise2() {
return new Promise(resolve => {
setTimeout(() => {
console.log('promise2 完成');
resolve('p2 value');
}, 2000);
});
}
// 链式调用中返回 Promise
promise1()
.then(value => {
console.log('then1 接收值:', value); // then1 接收值: p1 value
return promise2(); // x 是 Promise,触发解决过程
})
.then(value => {
console.log('then2 接收值:', value); // then2 接收值: p2 value(等待 promise2 完成)
})
.catch(error => {
console.log('错误:', error);
});
解决过程解析:
promise1完成后,then1返回promise2(x是 Promise)。[[Resolve]](promise2, x)执行:promise2处于pending,当前then2的 Promise 保持pending。- 当
promise2完成时,当前 Promise 以相同值完成,触发then2回调。
四、解决过程中的异常处理
javascript
const promise = new Promise(resolve => {
// 模拟 Thenable 中抛出异常
resolve({
then: function() {
throw new Error('Thenable 内部错误');
}
});
});
promise.then(
value => console.log('成功:', value),
reason => console.log('错误:', reason) // 输出:错误: Thenable 内部错误
);
异常流程:
resolve传入 Thenable 对象。- 获取
x.then时未出错,但调用x.then时抛出异常。 - 解决过程捕获异常,以该异常拒绝
promise。
五、解决过程的核心意义
- 保证状态一致性 :无论
x是普通值、Promise 还是 Thenable,解决过程确保promise状态与x正确关联。 - 支持链式调用 :通过递归处理
x,实现 Promise 链的无缝衔接。 - 兼容不同实现:使原生 Promise 与第三方 Promise 库(如 Bluebird)可相互操作。
理解 Promise 解决过程是掌握 Promise 异步编程的关键,尤其在处理复杂链式调用和异常场景时,能帮助开发者预测和调试代码行为。