从零实现Promise:手写核心逻辑与静态方法解析
2025.09.19 12:47浏览量:0简介:本文深入解析Promise核心机制,通过手写实现帮助开发者理解异步编程原理,重点实现Promise类、all方法及race方法,附带完整代码与测试用例。
从零实现Promise:手写核心逻辑与静态方法解析
Promise作为JavaScript异步编程的核心解决方案,其内部实现机制一直是前端开发者关注的重点。本文将通过手写实现的方式,深入解析Promise的核心逻辑,并重点实现all
和race
两个静态方法,帮助开发者建立完整的Promise知识体系。
一、Promise核心实现
1.1 基础类结构
一个完整的Promise实现需要包含以下核心要素:
- 三种状态:
pending
、fulfilled
、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);
}
}
}
1.2 then方法实现
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;
}
1.3 解析Promise决议过程
resolvePromise
函数处理thenable对象的解析,这是实现链式调用的关键:
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);
}
}
二、静态方法实现
2.1 Promise.all实现
all
方法接收一个Promise可迭代对象,返回一个新Promise:
- 所有输入Promise都成功时,返回按顺序包含结果的数组
- 任意一个Promise失败时,立即返回失败的Promise
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let completed = 0;
const length = promises.length;
if (length === 0) {
resolve(results);
return;
}
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
value => {
results[index] = value;
completed++;
if (completed === length) {
resolve(results);
}
},
reason => {
reject(reason);
}
);
});
});
}
2.2 Promise.race实现
race
方法返回第一个决议的Promise(无论成功或失败):
static race(promises) {
return new MyPromise((resolve, reject) => {
if (promises.length === 0) return;
promises.forEach(promise => {
MyPromise.resolve(promise).then(
value => resolve(value),
reason => reject(reason)
);
});
});
}
三、完整实现与测试
3.1 完整代码整合
将上述实现整合为完整类:
class MyPromise {
// ... 前文实现的constructor和then方法 ...
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) {
// ... 前文all实现 ...
}
static race(promises) {
// ... 前文race实现 ...
}
catch(onRejected) {
return this.then(null, onRejected);
}
finally(onFinally) {
return this.then(
value => MyPromise.resolve(onFinally()).then(() => value),
reason => MyPromise.resolve(onFinally()).then(() => { throw reason; })
);
}
}
3.2 测试用例示例
// 测试all方法
const promise1 = new MyPromise((resolve) => setTimeout(() => resolve(1), 100));
const promise2 = new MyPromise((resolve) => setTimeout(() => resolve(2), 200));
const promise3 = new MyPromise((resolve) => setTimeout(() => resolve(3), 300));
MyPromise.all([promise1, promise2, promise3])
.then(values => console.log(values)); // [1, 2, 3]
// 测试race方法
const fastPromise = new MyPromise(resolve => setTimeout(() => resolve('fast'), 100));
const slowPromise = new MyPromise(resolve => setTimeout(() => resolve('slow'), 500));
MyPromise.race([fastPromise, slowPromise])
.then(value => console.log(value)); // 'fast'
四、实现要点总结
- 状态管理:必须确保状态只能从pending变为fulfilled或rejected,且不可逆
- 异步执行:使用setTimeout或微任务队列确保then回调异步执行
- 链式调用:通过返回新Promise实现then方法的链式调用
- 错误处理:在executor和then回调中都需要捕获异常
- 静态方法:all和race都需要处理空数组和异常情况
五、实际应用建议
- 调试技巧:在实现过程中添加console.log跟踪状态变化
- 边界测试:重点测试以下场景:
- 空数组输入
- 包含非Promise值的数组
- 立即决议的Promise
- 抛出异常的回调
- 性能优化:对于all方法,可以使用计数器优化完成判断
- 类型检查:添加参数类型检查增强鲁棒性
通过本文的手写实现,开发者可以深入理解Promise的工作原理,这不仅有助于解决实际开发中的问题,也为学习更高级的异步编程模式(如Async/Await)打下坚实基础。完整实现约200行代码,建议在实际项目中逐步扩展功能,如添加catch、finally等API。
发表评论
登录后可评论,请前往 登录 或 注册