从零开始:手写实现Promise核心机制解析
2025.09.19 12:47浏览量:3简介:本文深入解析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); // 1return 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支持、取消功能等高级特性,进一步加深对异步编程的理解。

发表评论
登录后可评论,请前往 登录 或 注册