纯JavaScript手写Promise实现,包含详细注释和完整功能。
/**
* 手写Promise实现(符合Promise/A+规范)
* 包含完整注释,展示Promise内部工作原理
*/
// 定义Promise的三种状态常量
const PENDING = 'pending'; // 等待状态
const FULFILLED = 'fulfilled'; // 成功状态
const REJECTED = 'rejected'; // 失败状态
/**
* 手写Promise类
*/
class MyPromise {
/**
* 构造函数:接收一个执行器函数
* @param {Function} executor - 立即执行的函数,接收resolve和reject两个参数
*/
constructor(executor) {
// 初始化状态为pending
this.status = PENDING;
// 成功后的值(默认undefined)
this.value = undefined;
// 失败后的原因(默认undefined)
this.reason = undefined;
// 存储成功回调函数(支持多个then调用)
this.onFulfilledCallbacks = [];
// 存储失败回调函数
this.onRejectedCallbacks = [];
// 使用箭头函数绑定this,保证resolve和reject中的this指向当前Promise实例
const resolve = (value) => {
// 只有pending状态才能转换为fulfilled或rejected
if (this.status === PENDING) {
// 状态变为fulfilled
this.status = FULFILLED;
// 保存成功的值
this.value = value;
// 执行所有成功回调(异步执行,符合微任务特性)
this.onFulfilledCallbacks.forEach(callback => {
callback();
});
}
};
const reject = (reason) => {
// 只有pending状态才能转换
if (this.status === PENDING) {
// 状态变为rejected
this.status = REJECTED;
// 保存失败的原因
this.reason = reason;
// 执行所有失败回调
this.onRejectedCallbacks.forEach(callback => {
callback();
});
}
};
try {
// 立即执行executor
executor(resolve, reject);
} catch (error) {
// 如果执行器抛出异常,直接reject
reject(error);
}
}
/**
* then方法:注册成功和失败的回调
* @param {Function} onFulfilled - 成功回调
* @param {Function} onRejected - 失败回调
* @returns {MyPromise} 返回新的Promise,支持链式调用
*/
then(onFulfilled, onRejected) {
// 参数可选:如果不是函数,则忽略(值穿透)
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };
// 创建并返回一个新的Promise
const promise2 = new MyPromise((resolve, reject) => {
// 根据当前状态执行不同的逻辑
if (this.status === FULFILLED) {
// 使用setTimeout模拟微任务(实际Promise是微任务,这里用宏任务简化)
setTimeout(() => {
try {
// 执行成功回调
const x = onFulfilled(this.value);
// 处理回调返回值
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else {
// 状态为pending:将回调保存起来,等待状态改变后再执行
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise2;
}
/**
* 处理then回调返回值的核心方法
* @param {MyPromise} promise2 - 当前then返回的新Promise
* @param {*} x - 上一个then回调的返回值
* @param {Function} resolve - promise2的resolve
* @param {Function} reject - promise2的reject
*/
resolvePromise(promise2, x, resolve, reject) {
// 防止循环引用:如果x和promise2相同,则抛出错误
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
// 标记是否已经调用过,防止多次调用
let called = false;
// 如果x是MyPromise实例
if (x instanceof MyPromise) {
// 执行x,根据x的状态决定promise2的状态
x.then(
y => {
// 递归解析,直到x不是Promise为止
this.resolvePromise(promise2, y, resolve, reject);
},
r => {
reject(r);
}
);
}
// 如果x是对象或函数
else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
// 获取then方法(兼容第三方Promise)
const then = x.then;
if (typeof then === 'function') {
// 如果then是函数,说明x是一个thenable对象
then.call(
x,
y => {
if (called) return;
called = true;
// 递归解析
this.resolvePromise(promise2, y, resolve, reject);
},
r => {
if (called) return;
called = true;
reject(r);
}
);
} else {
// 普通对象,直接resolve
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
// 基础类型值,直接resolve
resolve(x);
}
}
/**
* catch方法:只处理失败情况
* @param {Function} onRejected
* @returns {MyPromise}
*/
catch(onRejected) {
return this.then(null, onRejected);
}
/**
* finally方法:无论成功失败都会执行
* @param {Function} callback
* @returns {MyPromise}
*/
finally(callback) {
return this.then(
value => MyPromise.resolve(callback()).then(() => value),
reason => MyPromise.resolve(callback()).then(() => { throw reason; })
);
}
/**
* 静态resolve方法
* @param {*} value
* @returns {MyPromise}
*/
static resolve(value) {
// 如果value已经是MyPromise实例,直接返回
if (value instanceof MyPromise) {
return value;
}
// 否则返回一个新的成功状态的Promise
return new MyPromise(resolve => resolve(value));
}
/**
* 静态reject方法
* @param {*} reason
* @returns {MyPromise}
*/
static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason));
}
/**
* 静态all方法:所有成功才成功,一个失败就失败
* @param {Array} promises
* @returns {MyPromise}
*/
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let count = 0;
const total = promises.length;
// 处理空数组
if (total === 0) {
resolve(results);
return;
}
promises.forEach((promise, index) => {
// 确保每个项都是Promise
MyPromise.resolve(promise).then(
value => {
results[index] = value;
count++;
// 所有都成功才resolve
if (count === total) {
resolve(results);
}
},
reason => {
// 任何一个失败直接reject
reject(reason);
}
);
});
});
}
/**
* 静态race方法:谁先改变状态就采用谁的结果
* @param {Array} promises
* @returns {MyPromise}
*/
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
MyPromise.resolve(promise).then(resolve, reject);
});
});
}
/**
* 静态allSettled:等待所有Promise完成,返回所有结果
* @param {Array} promises
* @returns {MyPromise}
*/
static allSettled(promises) {
return new MyPromise(resolve => {
const results = [];
let count = 0;
const total = promises.length;
if (total === 0) {
resolve(results);
return;
}
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
value => {
results[index] = { status: 'fulfilled', value };
count++;
if (count === total) resolve(results);
},
reason => {
results[index] = { status: 'rejected', reason };
count++;
if (count === total) resolve(results);
}
);
});
});
}
/**
* 静态any:只要有一个成功就成功,全部失败才失败
* @param {Array} promises
* @returns {MyPromise}
*/
static any(promises) {
return new MyPromise((resolve, reject) => {
const errors = [];
let count = 0;
const total = promises.length;
if (total === 0) {
reject(new AggregateError('All promises were rejected'));
return;
}
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
value => {
resolve(value);
},
reason => {
errors[index] = reason;
count++;
if (count === total) {
reject(new AggregateError(errors, 'All promises were rejected'));
}
}
);
});
});
}
}
// ------------------- 测试代码 -------------------
console.log('========== 手写Promise测试 ==========\n');
// 测试1:基础功能
console.log('测试1:基础功能');
const p1 = new MyPromise((resolve, reject) => {
console.log('执行器立即执行');
setTimeout(() => {
resolve('成功啦!');
// reject('失败啦!');
}, 1000);
});
p1.then(
value => {
console.log('成功回调:', value);
},
reason => {
console.log('失败回调:', reason);
}
);
// 测试2:链式调用
console.log('\n测试2:链式调用');
const p2 = new MyPromise(resolve => {
resolve(1);
});
p2.then(value => {
console.log('then1:', value);
return value + 1;
}).then(value => {
console.log('then2:', value);
return value + 1;
}).then(value => {
console.log('then3:', value);
});
// 测试3:静态resolve/reject
console.log('\n测试3:静态方法');
MyPromise.resolve('直接成功').then(console.log);
MyPromise.reject('直接失败').catch(console.log);
// 测试4:all方法
console.log('\n测试4:Promise.all');
const promises = [
MyPromise.resolve(1),
MyPromise.resolve(2),
new MyPromise(resolve => setTimeout(() => resolve(3), 100))
];
MyPromise.all(promises).then(
results => console.log('all结果:', results),
error => console.log('all错误:', error)
);
// 测试5:race方法
console.log('\n测试5:Promise.race');
const racePromises = [
new MyPromise(resolve => setTimeout(() => resolve('慢的'), 200)),
new MyPromise(resolve => setTimeout(() => resolve('快的'), 100)),
new MyPromise((resolve, reject) => setTimeout(() => reject('错误'), 50))
];
MyPromise.race(racePromises).then(
value => console.log('race胜出:', value),
reason => console.log('race失败:', reason)
);
// 测试6:allSettled
console.log('\n测试6:Promise.allSettled');
const mixedPromises = [
MyPromise.resolve(1),
MyPromise.reject('错误信息'),
new MyPromise(resolve => setTimeout(() => resolve(3), 50))
];
MyPromise.allSettled(mixedPromises).then(results => {
console.log('allSettled结果:', results);
});
// 测试7:any方法
console.log('\n测试7:Promise.any');
const anyPromises = [
MyPromise.reject('错误1'),
MyPromise.reject('错误2'),
MyPromise.resolve('成功!')
];
MyPromise.any(anyPromises).then(
value => console.log('any成功:', value),
error => console.log('any失败:', error)
);
// 测试8:catch和finally
console.log('\n测试8:catch和finally');
new MyPromise((resolve, reject) => {
reject('出错了');
})
.then(value => {
console.log('不会执行');
})
.catch(reason => {
console.log('catch捕获:', reason);
return '从错误中恢复';
})
.then(value => {
console.log('catch后的then:', value);
})
.finally(() => {
console.log('finally执行');
});
// 测试9:值穿透
console.log('\n测试9:值穿透');
MyPromise.resolve(42)
.then()
.then()
.then(value => {
console.log('值穿透结果:', value);
});
// 测试10:异常捕获
console.log('\n测试10:异常捕获');
new MyPromise(() => {
throw new Error('执行器内错误');
}).catch(error => {
console.log('捕获到执行器错误:', error.message);
});
// 测试11:then中抛出错误
MyPromise.resolve(10)
.then(value => {
console.log('then中值:', value);
throw new Error('then中抛出的错误');
})
.catch(error => {
console.log('捕获到then中错误:', error.message);
});
// 测试12:循环引用检测
console.log('\n测试12:循环引用检测');
const promiseA = new MyPromise(resolve => {
resolve(1);
});
const promiseB = promiseA.then(() => {
return promiseB; // 返回自身,应该报错
});
promiseB.catch(error => {
console.log('捕获到循环引用错误:', error.message);
});
// 测试13:多个then调用
console.log('\n测试13:多个then调用');
const p3 = new MyPromise(resolve => {
setTimeout(() => resolve('数据'), 100);
});
p3.then(value => console.log('then A:', value));
p3.then(value => console.log('then B:', value));
p3.then(value => console.log('then C:', value));
console.log('\n========== 测试完成 ==========');
这个手写Promise实现包含了:
📚 核心功能
- 三种状态管理:pending/fulfilled/rejected
- then方法:支持链式调用和值穿透
- catch方法:错误处理
- finally方法:无论成功失败都会执行
🔧 静态方法
- resolve:返回成功状态的Promise
- reject:返回失败状态的Promise
- all:所有成功才成功,一个失败即失败
- race:竞速,返回第一个改变状态的Promise
- allSettled:等待所有完成,返回所有结果
- any:一个成功即成功,全部失败才失败
⚙️ 内部机制
- 状态不可逆:pending -> fulfilled/rejected,不可逆转
- 回调存储:支持多个then同时注册
- 值穿透:then中可以传非函数参数
- 循环引用检测:防止then返回自身
- thenable处理:兼容其他Promise库
- 异步执行:使用setTimeout模拟微任务