Appearance
Promise 的内部机制:PromiseJobs 与微任务队列
Promise是JavaScript异步编程的核心,它与事件循环紧密协作。当你调用then()方法时,回调函数不会立即执行,而是被放入微任务队列。V8如何实现这一机制?Promise内部的状态转换是怎样的?本章将揭示Promise的底层实现。
Promise的状态模型
Promise有三种状态:
javascript
// Promise状态
class PromiseStates {
static demonstrate() {
console.log('=== Promise的三种状态 ===\n');
console.log('状态定义:');
console.log(' • pending - 初始状态,等待中');
console.log(' • fulfilled - 已成功,有结果值');
console.log(' • rejected - 已失败,有失败原因\n');
console.log('状态转换规则:');
console.log('');
console.log(' ┌─────────────────┐');
console.log(' │ pending │');
console.log(' └────────┬────────┘');
console.log(' │');
console.log(' ┌────────┴────────┐');
console.log(' ↓ ↓');
console.log(' ┌───────────┐ ┌───────────┐');
console.log(' │ fulfilled │ │ rejected │');
console.log(' └───────────┘ └───────────┘');
console.log('');
console.log('关键规则:');
console.log(' • 状态只能从pending转换');
console.log(' • 转换后状态不可再变');
console.log(' • 结果值或原因不可修改\n');
}
static demonstrateExample() {
console.log('=== 状态转换示例 ===\n');
// 创建Promise
const promise = new Promise((resolve, reject) => {
console.log('1. Promise创建,状态:pending');
setTimeout(() => {
resolve('成功');
console.log('2. 调用resolve,状态:fulfilled');
// 再次调用无效
reject('失败');
console.log('3. 调用reject无效,状态仍是fulfilled');
}, 100);
});
return promise;
}
static async runAll() {
this.demonstrate();
await this.demonstrateExample();
}
}
PromiseStates.runAll();V8中的Promise对象结构
V8如何存储Promise:
javascript
// V8 Promise内部结构
class V8PromiseStructure {
static demonstrate() {
console.log('=== V8 Promise内部结构 ===\n');
console.log('JSPromise对象布局:');
console.log(`
class JSPromise {
// 继承自JSObject
Map* map; // 隐藏类
// Promise特有字段
reactions_or_result; // 状态相关数据
flags; // 状态标志位
}
`);
console.log('flags字段位布局:');
console.log(' ┌─────────────────────────────────┐');
console.log(' │ bit 0-1 │ status (状态) │');
console.log(' │ bit 2 │ has_handler (有处理器) │');
console.log(' │ bit 3 │ handled_hint │');
console.log(' │ bit 4 │ async_task_id │');
console.log(' └─────────────────────────────────┘\n');
console.log('status值含义:');
console.log(' 0 = pending');
console.log(' 1 = fulfilled');
console.log(' 2 = rejected\n');
}
static demonstrateReactionsOrResult() {
console.log('=== reactions_or_result字段 ===\n');
console.log('该字段根据状态存储不同内容:');
console.log('');
console.log(' pending状态:');
console.log(' 存储PromiseReaction链表');
console.log(' (等待状态变化时执行的回调)');
console.log('');
console.log(' fulfilled状态:');
console.log(' 存储fulfillment值');
console.log(' (resolve传入的值)');
console.log('');
console.log(' rejected状态:');
console.log(' 存储rejection原因');
console.log(' (reject传入的值)\n');
}
static runAll() {
this.demonstrate();
this.demonstrateReactionsOrResult();
}
}
V8PromiseStructure.runAll();PromiseReaction:回调的存储结构
当调用then()时,V8创建PromiseReaction:
javascript
// PromiseReaction结构
class PromiseReactionStructure {
static demonstrate() {
console.log('=== PromiseReaction结构 ===\n');
console.log('每个then()调用创建一个PromiseReaction:');
console.log(`
class PromiseReaction {
next; // 下一个Reaction(链表)
promise_or_capability; // 返回的新Promise
fulfill_handler; // onFulfilled回调
reject_handler; // onRejected回调
}
`);
console.log('示例代码:');
console.log(`
const p = new Promise(resolve => resolve(1));
p.then(onFulfilled1, onRejected1);
p.then(onFulfilled2, onRejected2);
`);
console.log('内部结构:');
console.log('');
console.log(' JSPromise p');
console.log(' │');
console.log(' └─ reactions_or_result');
console.log(' │');
console.log(' ↓');
console.log(' ┌────────────────────┐');
console.log(' │ PromiseReaction #1 │');
console.log(' │ fulfill: handler1 │');
console.log(' │ reject: handler1 │');
console.log(' └─────────┬──────────┘');
console.log(' │ next');
console.log(' ↓');
console.log(' ┌────────────────────┐');
console.log(' │ PromiseReaction #2 │');
console.log(' │ fulfill: handler2 │');
console.log(' │ reject: handler2 │');
console.log(' └────────────────────┘');
console.log('');
}
static runAll() {
this.demonstrate();
}
}
PromiseReactionStructure.runAll();resolve和reject的实现
状态转换的内部流程:
javascript
// resolve/reject实现
class ResolveRejectImplementation {
static demonstrateResolve() {
console.log('=== resolve实现流程 ===\n');
console.log('FulfillPromise伪代码:');
console.log(`
function FulfillPromise(promise, value) {
// 1. 检查状态
if (promise.status !== PENDING) return;
// 2. 获取reactions链表
const reactions = promise.reactions_or_result;
// 3. 设置结果值
promise.reactions_or_result = value;
// 4. 更新状态
promise.status = FULFILLED;
// 5. 触发所有reaction
TriggerPromiseReactions(reactions, value, FULFILL);
}
`);
}
static demonstrateTrigger() {
console.log('=== TriggerPromiseReactions ===\n');
console.log('触发reactions的流程:');
console.log(`
function TriggerPromiseReactions(reactions, value, type) {
// 遍历reaction链表
while (reactions !== null) {
const reaction = reactions;
reactions = reaction.next;
// 创建PromiseReactionJob
const job = new PromiseReactionJob(reaction, value, type);
// 加入微任务队列
EnqueueMicrotask(job);
}
}
`);
console.log('关键点:');
console.log(' • reactions不是直接执行');
console.log(' • 而是包装成PromiseReactionJob');
console.log(' • 放入微任务队列等待执行\n');
}
static runAll() {
this.demonstrateResolve();
this.demonstrateTrigger();
}
}
ResolveRejectImplementation.runAll();PromiseReactionJob:微任务的核心
每个Promise回调都是一个PromiseReactionJob:
javascript
// PromiseReactionJob
class PromiseReactionJobDetail {
static demonstrate() {
console.log('=== PromiseReactionJob执行流程 ===\n');
console.log('Job执行伪代码:');
console.log(`
function PromiseReactionJob(reaction, value, type) {
// 获取处理器
const handler = type === FULFILL
? reaction.fulfill_handler
: reaction.reject_handler;
// 获取返回的Promise
const promiseCapability = reaction.promise_or_capability;
try {
// 执行回调
let result;
if (handler === undefined) {
// 没有处理器,直接传递值
result = value;
} else {
// 调用处理器
result = handler(value);
}
// 解析返回的Promise
Resolve(promiseCapability.promise, result);
} catch (error) {
// 处理器抛出异常
Reject(promiseCapability.promise, error);
}
}
`);
}
static demonstrateChaining() {
console.log('=== Promise链式调用原理 ===\n');
console.log('代码:');
console.log(`
Promise.resolve(1)
.then(x => x + 1)
.then(x => x * 2)
.then(console.log); // 输出 4
`);
console.log('执行过程:');
console.log('');
console.log(' 1. Promise.resolve(1) 创建 p1 (fulfilled, 值=1)');
console.log('');
console.log(' 2. p1.then(x => x + 1) 创建 p2 (pending)');
console.log(' PromiseReactionJob入队:{handler: x=>x+1, promise: p2}');
console.log('');
console.log(' 3. p2.then(x => x * 2) 创建 p3 (pending)');
console.log(' p3等待p2');
console.log('');
console.log(' 4. p3.then(console.log) 创建 p4 (pending)');
console.log(' p4等待p3');
console.log('');
console.log(' 5. 微任务执行:');
console.log(' - Job1执行: 1+1=2, resolve(p2, 2)');
console.log(' - Job2入队: {handler: x=>x*2, promise: p3}');
console.log(' - Job2执行: 2*2=4, resolve(p3, 4)');
console.log(' - Job3入队: {handler: console.log, promise: p4}');
console.log(' - Job3执行: console.log(4)');
console.log('');
}
static runAll() {
this.demonstrate();
this.demonstrateChaining();
}
}
PromiseReactionJobDetail.runAll();then的完整实现
then方法的内部逻辑:
javascript
// then方法实现
class ThenImplementation {
static demonstrate() {
console.log('=== Promise.prototype.then实现 ===\n');
console.log('伪代码:');
console.log(`
Promise.prototype.then = function(onFulfilled, onRejected) {
// 1. 创建新的Promise(用于返回)
const resultCapability = NewPromiseCapability();
// 2. 创建PromiseReaction
const reaction = {
promise_or_capability: resultCapability,
fulfill_handler: onFulfilled,
reject_handler: onRejected,
next: null
};
// 3. 根据当前状态处理
if (this.status === PENDING) {
// pending: 添加到reactions链表
AppendReaction(this, reaction);
} else if (this.status === FULFILLED) {
// fulfilled: 直接创建Job入队
const job = new PromiseReactionJob(
reaction,
this.reactions_or_result, // 结果值
FULFILL
);
EnqueueMicrotask(job);
} else {
// rejected: 直接创建Job入队
const job = new PromiseReactionJob(
reaction,
this.reactions_or_result, // 失败原因
REJECT
);
EnqueueMicrotask(job);
}
// 4. 返回新Promise
return resultCapability.promise;
};
`);
}
static demonstrateCapability() {
console.log('=== PromiseCapability ===\n');
console.log('PromiseCapability结构:');
console.log(`
class PromiseCapability {
promise; // 新创建的Promise
resolve; // 控制该Promise的resolve函数
reject; // 控制该Promise的reject函数
}
`);
console.log('作用:');
console.log(' • 保存对新Promise的控制权');
console.log(' • 允许在handler执行后决议新Promise');
console.log(' • 实现链式调用的关键\n');
}
static runAll() {
this.demonstrate();
this.demonstrateCapability();
}
}
ThenImplementation.runAll();模拟Promise实现
通过代码理解Promise核心机制:
javascript
// 简化版Promise实现
class SimplePromise {
static PENDING = 'pending';
static FULFILLED = 'fulfilled';
static REJECTED = 'rejected';
constructor(executor) {
this.status = SimplePromise.PENDING;
this.value = undefined;
this.reactions = [];
const resolve = (value) => {
if (this.status !== SimplePromise.PENDING) return;
this.status = SimplePromise.FULFILLED;
this.value = value;
// 触发所有reaction
this.reactions.forEach(reaction => {
queueMicrotask(() => {
this._executeReaction(reaction, 'fulfill');
});
});
};
const reject = (reason) => {
if (this.status !== SimplePromise.PENDING) return;
this.status = SimplePromise.REJECTED;
this.value = reason;
this.reactions.forEach(reaction => {
queueMicrotask(() => {
this._executeReaction(reaction, 'reject');
});
});
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
return new SimplePromise((resolve, reject) => {
const reaction = {
onFulfilled,
onRejected,
resolve,
reject
};
if (this.status === SimplePromise.PENDING) {
this.reactions.push(reaction);
} else {
queueMicrotask(() => {
this._executeReaction(
reaction,
this.status === SimplePromise.FULFILLED ? 'fulfill' : 'reject'
);
});
}
});
}
_executeReaction(reaction, type) {
const handler = type === 'fulfill'
? reaction.onFulfilled
: reaction.onRejected;
try {
if (typeof handler === 'function') {
const result = handler(this.value);
reaction.resolve(result);
} else {
// 没有处理器,透传
if (type === 'fulfill') {
reaction.resolve(this.value);
} else {
reaction.reject(this.value);
}
}
} catch (error) {
reaction.reject(error);
}
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
static resolve(value) {
return new SimplePromise(resolve => resolve(value));
}
static reject(reason) {
return new SimplePromise((_, reject) => reject(reason));
}
}
// 测试
console.log('=== SimplePromise测试 ===\n');
SimplePromise.resolve(1)
.then(x => {
console.log('第一个then:', x);
return x + 1;
})
.then(x => {
console.log('第二个then:', x);
return x * 2;
})
.then(x => {
console.log('第三个then:', x);
});
console.log('同步代码结束\n');Promise.all和Promise.race
聚合方法的实现原理:
javascript
// Promise.all实现
class PromiseAggregation {
static demonstrateAll() {
console.log('=== Promise.all实现原理 ===\n');
console.log('伪代码:');
console.log(`
Promise.all = function(promises) {
return new Promise((resolve, reject) => {
const results = [];
let remaining = promises.length;
if (remaining === 0) {
resolve(results);
return;
}
promises.forEach((promise, index) => {
Promise.resolve(promise).then(
value => {
results[index] = value;
remaining--;
if (remaining === 0) {
resolve(results);
}
},
reason => {
// 任一拒绝,整体拒绝
reject(reason);
}
);
});
});
};
`);
console.log('关键点:');
console.log(' • 结果数组保持原始顺序');
console.log(' • 使用计数器跟踪完成数');
console.log(' • 任一拒绝立即结束\n');
}
static demonstrateRace() {
console.log('=== Promise.race实现原理 ===\n');
console.log('伪代码:');
console.log(`
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
promises.forEach(promise => {
Promise.resolve(promise).then(resolve, reject);
});
});
};
`);
console.log('关键点:');
console.log(' • 第一个完成的决定结果');
console.log(' • 后续完成的被忽略');
console.log(' • 状态只能转换一次\n');
}
static runAll() {
this.demonstrateAll();
this.demonstrateRace();
}
}
PromiseAggregation.runAll();微任务队列与Promise的协作
Promise如何与微任务队列配合:
javascript
// 微任务队列协作
class MicrotaskCooperation {
static demonstrate() {
console.log('=== Promise与微任务队列 ===\n');
console.log('代码示例:');
console.log(`
console.log('1');
Promise.resolve()
.then(() => {
console.log('2');
return Promise.resolve();
})
.then(() => {
console.log('3');
});
Promise.resolve().then(() => {
console.log('4');
});
console.log('5');
`);
console.log('执行分析:');
console.log('');
console.log(' 同步执行:');
console.log(' 输出 1');
console.log(' Job A入队(输出2的那个)');
console.log(' Job B入队(输出4的那个)');
console.log(' 输出 5');
console.log('');
console.log(' 微任务执行:');
console.log(' Job A: 输出 2,return Promise.resolve()');
console.log(' 这里产生额外的微任务!');
console.log(' Job B: 输出 4');
console.log(' Job C: Promise.resolve()的内部处理');
console.log(' Job D: 输出 3');
console.log('');
console.log(' 最终输出:1 → 5 → 2 → 4 → 3');
console.log('');
}
static demonstrateThenable() {
console.log('=== then中返回Promise ===\n');
console.log('返回Promise时的特殊处理:');
console.log(`
// 当handler返回一个Promise时
.then(() => {
return Promise.resolve(value);
})
// V8的处理步骤:
// 1. handler执行完成
// 2. 发现返回值是Promise
// 3. 创建PromiseResolveThenableJob
// 4. 该Job会等待返回的Promise
// 5. 这会额外消耗1-2个微任务周期
`);
console.log('性能建议:');
console.log(' • 避免不必要的Promise包装');
console.log(' • 直接返回值比返回Promise快');
console.log(' • async函数自动处理这个问题\n');
}
static runAll() {
this.demonstrate();
this.demonstrateThenable();
}
}
MicrotaskCooperation.runAll();性能优化
Promise使用的性能考量:
javascript
// Promise性能优化
class PromisePerformance {
static demonstrateAvoidUnnecessaryPromise() {
console.log('=== 避免不必要的Promise ===\n');
console.log('不推荐:');
console.log(`
// 冗余的Promise.resolve
async function getData() {
const data = await fetch('/api');
return Promise.resolve(data); // 不必要
}
`);
console.log('推荐:');
console.log(`
async function getData() {
const data = await fetch('/api');
return data; // async自动包装
}
`);
}
static demonstrateBatchPromises() {
console.log('=== 批量Promise处理 ===\n');
console.log('串行(慢):');
console.log(`
// 每个请求等前一个完成
for (const url of urls) {
await fetch(url); // 串行执行
}
`);
console.log('并行(快):');
console.log(`
// 所有请求同时发起
await Promise.all(urls.map(url => fetch(url)));
`);
console.log('受控并发(最佳):');
console.log(`
// 限制同时进行的请求数
async function parallelLimit(tasks, limit) {
const results = [];
const executing = [];
for (const task of tasks) {
const p = Promise.resolve().then(() => task());
results.push(p);
if (tasks.length >= limit) {
const e = p.then(() => {
executing.splice(executing.indexOf(e), 1);
});
executing.push(e);
if (executing.length >= limit) {
await Promise.race(executing);
}
}
}
return Promise.all(results);
}
`);
}
static runAll() {
this.demonstrateAvoidUnnecessaryPromise();
this.demonstrateBatchPromises();
}
}
PromisePerformance.runAll();本章小结
本章深入探讨了Promise的内部实现机制。核心要点包括:
状态模型:Promise有pending、fulfilled、rejected三种状态,状态转换不可逆。
内部结构:V8的JSPromise对象包含flags(状态标志)和reactions_or_result(反应链表或结果值)。
PromiseReaction:每个then()调用创建一个PromiseReaction,存储回调函数和返回的Promise。
PromiseReactionJob:当Promise状态改变时,V8将每个reaction包装成Job放入微任务队列。
then实现:根据当前状态决定是添加到reactions链表还是直接入队微任务。
链式调用:每个then返回新Promise,handler的返回值决定新Promise的状态。
性能考量:避免不必要的Promise包装,合理使用并行和批量处理。
理解Promise的内部机制,能帮助你写出更高效的异步代码,也能更好地调试异步问题。下一章我们将探讨async/await的底层实现,了解它如何被转换为Promise和生成器。