Promise 理解
Promise 执行顺序总结分析
代码分析
javascript
const p1 = Promise.resolve(1);
const p2 = new Promise(resolve => resolve(p1));
p2.then(res => console.log(2));
p1.then(() => console.log(1)).then(() => console.log(4));
console.log(3);
执行顺序
输出结果:3, 1, 4, 2
详细执行过程
1. Promise 创建阶段
- 创建 p1:
Promise.resolve(1)
创建一个已解决(fulfilled)的 Promise,值为 1 - 创建
p2
:调用Promise.resolve()
,传入一个 executor 函数resolve => resolve(p1)
2. p2
构造过程详解
当执行 p2
的构造函数时:
- 立即执行传入的 executor:
resolve => resolve(p1)
- 调用内部的
resolve
函数,参数为p1
- 进入
resolvePromise
函数处理:javascriptif (value instanceof Promise) { // value 是 p1 value.then(resolve, reject); // 关键:建立依赖关系 return; }
- 由于
p1
已经是 fulfilled 状态,p1.then(resolve, reject)
会将p2
的 resolve/reject 函数加入微任务队列
3. 回调注册顺序
按时间顺序注册的回调:
p1.then(p2_resolve, p2_reject)
- 来自resolvePromise
内部调用p1.then(() => console.log(1))
- 显式注册到p1
.then(() => console.log(4))
- 链式 Promise 的回调p2.then(res => console.log(2))
- 注册到p2
4. 微任务队列执行
微任务执行顺序:
p2_resolve
- 使p2
变为 fulfilled 状态,触发p2.then
回调注册() => console.log(1)
-p1
的第一个回调() => console.log(4)
- 链式 Promise 回调() => console.log(2)
-p2
的回调(在步骤 1 中触发注册)
5. 最终输出
3 // 同步代码立即执行
1 // p1 的第一个回调
4 // 链式 Promise 回调
2 // p2 的回调
核心要点
- Promise 解析机制:当一个 Promise 被 resolve 为另一个 Promise 时,会通过
then
方法建立依赖关系 - 微任务队列:Promise 回调都放入微任务队列,按注册顺序执行
- 状态传播:
p2
的状态依赖于p1
,只有p1
完成后p2
才能变为 fulfilled - 执行时机:虽然
p2
的 resolve 函数注册最早,但p2.then
的回调是在p2
状态改变后才注册的,所以执行较晚
这个例子完美展示了 Promise 的异步特性、状态传播机制以及微任务队列的执行顺序。
拓展
js
const p1 = Promise.resolve(1);
const p2 = new Promise(resolve => resolve(p1));
p2.then(res => console.log(2));
p1.then(() => console.log(1)).then(() => console.log(4));
console.log(3);
// 对比下面的代码 输出结果有何不同,理解什么是promise吸收
const p3 = Promise.resolve(1);
const p4 = Promise.resolve(resolve => resolve(p3));
p4.then(res => console.log(2));
p3.then(() => console.log(1)).then(() => console.log(4));
console.log(3);