Promise 解决过程(Promise Resolution Procedure)详解
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
,避免循环引用。 -
示例:
const 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
。
- 若
-
示例:
function 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
。
- 尝试获取
-
示例:
// 定义 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
。 -
示例:
const promise = new Promise(resolve => { resolve(42); // x 是普通值 }); promise.then( value => console.log('普通值结果:', value), // 输出:普通值结果: 42 reason => console.log('错误:', reason) );
三、解决过程在链式调用中的体现
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
回调。
-
四、解决过程中的异常处理
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 异步编程的关键,尤其在处理复杂链式调用和异常场景时,能帮助开发者预测和调试代码行为。