从零开始:手写实现Promise核心机制解析
2025.09.19 12:47浏览量:0简介:本文深入解析Promise核心机制,通过手写实现完整功能,涵盖状态管理、链式调用、异步处理等关键特性,帮助开发者理解其底层原理。
从零开始:手写实现Promise核心机制解析
Promise作为JavaScript异步编程的核心解决方案,其设计思想深刻影响了现代前端开发。本文将通过手写实现一个简化版Promise,深入解析其工作原理,帮助开发者理解状态管理、链式调用、异步处理等核心机制。
一、Promise基础架构设计
1.1 核心状态定义
Promise规范定义了三种状态:pending
、fulfilled
和rejected
。状态转换具有单向性:
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
this.state = PENDING; // 初始状态
this.value = undefined; // 成功值
this.reason = undefined; // 失败原因
this.onFulfilledCallbacks = []; // 成功回调队列
this.onRejectedCallbacks = []; // 失败回调队列
}
}
状态机设计确保了Promise的确定性行为,这是链式调用和异常处理的基础。
1.2 执行器函数解析
执行器函数接收resolve
和reject
两个参数,这两个方法需要处理状态变更和回调执行:
resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
// 执行所有成功回调
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
// 执行所有失败回调
this.onRejectedCallbacks.forEach(fn => fn());
}
};
异步执行要求通过try/catch
包裹执行器,防止未捕获异常导致进程崩溃。
二、核心方法实现
2.1 then方法实现
then
方法需要处理同步/异步结果、值穿透和链式调用:
then(onFulfilled, onRejected) {
// 参数可选处理
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };
const promise2 = new MyPromise((resolve, reject) => {
if (this.state === FULFILLED) {
// 模拟异步执行
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
} else if (this.state === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
} else if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
}
通过返回新的Promise实例实现链式调用,使用setTimeout
模拟微任务队列。
2.2 resolvePromise解析
处理thenable对象和Promise的递归解析是关键:
function resolvePromise(promise2, x, resolve, reject) {
// 防止循环引用
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
let called = false;
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
const then = x.then;
if (typeof then === 'function') {
then.call(
x,
y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
r => {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
该实现遵循Promise/A+规范,处理了各种边界情况。
三、静态方法实现
3.1 resolve/reject方法
static resolve(value) {
if (value instanceof MyPromise) {
return value;
}
return new MyPromise(resolve => resolve(value));
}
static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason));
}
3.2 all方法实现
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let count = 0;
if (promises.length === 0) {
resolve(results);
}
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
value => {
results[index] = value;
count++;
if (count === promises.length) {
resolve(results);
}
},
reason => reject(reason)
);
});
});
}
3.3 race方法实现
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
MyPromise.resolve(promise).then(resolve, reject);
});
});
}
四、实际应用与调试技巧
4.1 常见问题排查
- 状态不可变:确保状态只能从pending转为fulfilled/rejected一次
- 回调执行顺序:使用
setTimeout
模拟微任务队列 - 值穿透处理:then方法的可选参数处理
4.2 性能优化建议
- 使用数组存储回调而非多次push
- 对已决议的Promise立即执行回调
- 实现微任务队列(实际开发中可使用MutationObserver或MessageChannel)
4.3 测试用例设计
// 基础测试
const p = new MyPromise((resolve) => {
setTimeout(() => resolve(1), 100);
});
p.then(value => {
console.log(value); // 1
return value + 1;
}).then(value => {
console.log(value); // 2
});
// 异常处理测试
MyPromise.reject('error')
.catch(e => {
console.log(e); // 'error'
return 'recovered';
})
.then(v => console.log(v)); // 'recovered'
五、完整实现代码
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
this.state = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };
const promise2 = new MyPromise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
} else if (this.state === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
} else if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
}
catch(onRejected) {
return this.then(null, onRejected);
}
finally(callback) {
return this.then(
value => MyPromise.resolve(callback()).then(() => value),
reason => MyPromise.resolve(callback()).then(() => { throw reason; })
);
}
static resolve(value) {
if (value instanceof MyPromise) {
return value;
}
return new MyPromise(resolve => resolve(value));
}
static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason));
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let count = 0;
if (promises.length === 0) {
resolve(results);
}
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
value => {
results[index] = value;
count++;
if (count === promises.length) {
resolve(results);
}
},
reason => reject(reason)
);
});
});
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
MyPromise.resolve(promise).then(resolve, reject);
});
});
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
let called = false;
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
const then = x.then;
if (typeof then === 'function') {
then.call(
x,
y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
r => {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
总结
通过手写实现Promise,我们深入理解了其状态管理、链式调用和异步处理机制。关键实现要点包括:
- 严格的状态转换规则
- 回调队列的异步执行
- thenable对象的递归解析
- 静态方法的完整实现
这种实现虽然简化了部分细节(如真正的微任务调度),但完整遵循了Promise/A+规范的核心逻辑。开发者可以通过扩展这个基础实现,添加async/await支持、取消功能等高级特性,进一步加深对异步编程的理解。
发表评论
登录后可评论,请前往 登录 或 注册