手写Promise核心实现与静态方法解析:all与race的深度实践
2025.09.19 12:47浏览量:1简介:本文通过手写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,在需要特殊功能时再考虑自定义实现。
发表评论
登录后可评论,请前往 登录 或 注册