简介:本文通过分步拆解Promise核心机制,结合代码示例与状态转换图,用最直观的方式讲解如何手写一个符合A+规范的Promise。涵盖异步任务管理、链式调用、错误处理等关键功能,并提供可运行的完整实现代码。
在前端开发中,Promise已成为处理异步操作的标准方案。但多数开发者仅停留在then/catch的表面使用,对内部实现机制缺乏深入理解。手写Promise不仅能加深对异步编程的理解,更能帮助解决以下实际问题:
本文将通过最简化的实现路径,逐步构建一个符合Promise/A+规范的完整实现,确保每个步骤都有明确的解释。
Promise本质是一个状态机,包含三种状态:
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 = [];}}
状态转换规则:
resolve或reject方法触发Promise通过维护两个回调队列实现异步处理:
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());}};
这种设计确保了:
class MyPromise {constructor(executor) {this.state = PENDING;this.value = undefined;this.reason = undefined;this.onFulfilledCallbacks = [];this.onRejectedCallbacks = [];const resolve = (value) => {// 实现待补充};const reject = (reason) => {// 实现待补充};try {executor(resolve, reject);} catch (err) {reject(err);}}}
then方法是Promise的核心,需要处理:
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规范最关键的部分,需要处理:
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);}}
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 (err) {reject(err);}}then(onFulfilled, onRejected) {onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };const promise2 = new MyPromise((resolve, reject) => {const handleFulfilled = () => {setTimeout(() => {try {const x = onFulfilled(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);};const handleRejected = () => {setTimeout(() => {try {const x = onRejected(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);};if (this.state === FULFILLED) {handleFulfilled();} else if (this.state === REJECTED) {handleRejected();} else if (this.state === PENDING) {this.onFulfilledCallbacks.push(handleFulfilled);this.onRejectedCallbacks.push(handleRejected);}});return promise2;}// 添加catch方法增强实用性catch(onRejected) {return this.then(null, onRejected);}// 添加静态resolve方法static resolve(value) {if (value instanceof MyPromise) {return value;}return new MyPromise(resolve => resolve(value));}}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);}}
测试验证:使用Promises/A+测试套件验证实现正确性
npm install promises-aplus-tests -gpromises-aplus-tests your-promise-implementation.js
性能优化:
queueMicrotask替代setTimeout实现更精确的微任务调度扩展功能:
finally方法all、race等静态方法调试技巧:
inspect方法便于调试通过分步实现,我们构建了一个符合Promise/A+规范的完整实现。关键点包括:
这种实现方式不仅加深了对Promise原理的理解,更为自定义异步控制提供了基础。实际开发中,可根据具体需求在此基础上进行扩展优化,构建更符合业务场景的异步解决方案。