手写Promise核心实现与静态方法解析:all与race的深度实践
2025.09.19 12:47浏览量:3简介:本文通过手写Promise类及静态方法all/race,深度解析异步编程核心机制,结合代码示例与场景分析,帮助开发者掌握Promise底层原理并提升实战能力。
一、Promise核心机制解析
1.1 Promise基础规范
Promise是ES6引入的异步解决方案,遵循Promises/A+规范,包含三种状态:
- Pending(初始态)
- Fulfilled(成功态)
- Rejected(失败态)
状态转换具有不可逆性,一旦从Pending转为Fulfilled/Rejected,将永久保持该状态。
1.2 手写Promise类实现
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) => {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;}}
关键实现点:
- 状态管理:通过闭包保存resolve/reject方法
- 异步调度:使用setTimeout确保then方法异步执行
- 链式调用:每次then返回新Promise实例
- 错误处理:try-catch包裹执行过程
1.3 resolvePromise解析
function resolvePromise(promise2, x, resolve, reject) {if (promise2 === x) {return reject(new TypeError('Chaining cycle detected'));}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对象处理
- 状态变更的唯一性保证
二、静态方法实现
2.1 Promise.all实现
MyPromise.all = function(promises) {return new MyPromise((resolve, reject) => {const results = [];let count = 0;if (promises.length === 0) {resolve(results);return;}promises.forEach((promise, index) => {// 处理非Promise值MyPromise.resolve(promise).then(value => {results[index] = value;count++;if (count === promises.length) {resolve(results);}},reason => {reject(reason);});});});};
关键特性:
- 参数校验:自动包装非Promise值
- 顺序保持:结果数组与输入顺序一致
- 短路机制:第一个rejected即终止
- 空数组处理:直接resolve空数组
2.2 Promise.race实现
MyPromise.race = function(promises) {return new MyPromise((resolve, reject) => {if (promises.length === 0) {return; // 规范未定义空数组行为,此处保持静默}promises.forEach(promise => {MyPromise.resolve(promise).then(value => resolve(value),reason => reject(reason));});});};
特性说明:
- 竞速机制:第一个完成(无论成功失败)的Promise决定结果
- 参数处理:同样支持非Promise值
- 空数组处理:规范未明确,实际实现可能挂起
三、实战应用场景
3.1 并发请求控制
// 同时发起多个API请求function fetchAllData(urls) {return MyPromise.all(urls.map(url =>fetch(url).then(res => res.json())));}// 优先获取最快响应function getFastestResponse(urls) {return MyPromise.race(urls.map(url =>fetch(url).then(res => res.json())));}
3.2 超时控制实现
function timeoutPromise(promise, ms) {return MyPromise.race([promise,new MyPromise((_, reject) =>setTimeout(() => reject(new Error('Timeout')), ms))]);}// 使用示例timeoutPromise(fetch('https://api.example.com'), 5000).then(data => console.log(data)).catch(err => console.error(err.message));
四、常见问题与解决方案
4.1 内存泄漏风险
问题:未清理的回调队列可能导致内存泄漏
解决方案:
// 在Promise类中添加取消机制class CancelablePromise extends MyPromise {constructor(executor) {super(executor);this.cancelHandlers = [];}cancel(reason) {this.cancelHandlers.forEach(handler => handler(reason));this.reject(new Error(`Canceled: ${reason}`));}then(onFulfilled, onRejected) {const promise2 = super.then(onFulfilled, onRejected);if (typeof onFulfilled === 'function') {this.cancelHandlers.push(() => {onFulfilled = null; // 清理引用});}return promise2;}}
4.2 错误处理最佳实践
- 始终在Promise链末尾添加.catch()
- 使用async/await时配合try-catch
- 区分可恢复错误和致命错误
五、性能优化建议
- 批量处理:对于大量Promise,考虑分批处理
并发控制:使用信号量模式限制并发数
class PromisePool {constructor(maxConcurrent) {this.maxConcurrent = maxConcurrent;this.running = 0;this.queue = [];}add(promiseGenerator) {return new MyPromise((resolve, reject) => {this.queue.push({ promiseGenerator, resolve, reject });this.run();});}run() {while (this.running < this.maxConcurrent && this.queue.length) {const { promiseGenerator, resolve, reject } = this.queue.shift();this.running++;promiseGenerator().then(resolve, reject).finally(() => {this.running--;this.run();});}}}
缓存策略:对重复请求使用Memoization
六、总结与展望
通过手写实现Promise核心机制,我们深入理解了:
- 状态机的设计原理
- 异步调度的实现技巧
- 链式调用的延续性保证
- 错误传播的机制
未来发展方向:
- 支持Async/Await语法
- 实现Promise.try统一同步/异步错误处理
- 添加进度通知能力
- 集成取消令牌模式
完整实现代码已覆盖Promise核心功能,开发者可通过扩展上述基础实现,构建更强大的异步控制工具。建议在实际项目中先使用原生Promise,在需要特殊功能时再考虑自定义实现。

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