实现一个简版Promise
手写实现一个符合Promise/A+规范的简版Promise,理解异步编程的原理
问题
Promise是JavaScript中处理异步操作的重要机制。这道题要求实现一个简版的Promise,需要支持:
- 三种状态:pending、fulfilled、rejected
- then方法的链式调用
- 异步状态改变
- 值的传递和错误捕获
通过手写Promise,可以理解异步编程的原理和Promise的内部实现机制。
解答
// 定义三种状态常量
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
// 初始状态为pending
this.status = PENDING;
// 成功的值
this.value = undefined;
// 失败的原因
this.reason = undefined;
// 成功回调函数队列
this.onFulfilledCallbacks = [];
// 失败回调函数队列
this.onRejectedCallbacks = [];
// resolve函数
const resolve = (value) => {
// 只有pending状态才能转换
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
// 执行所有成功回调
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
// reject函数
const reject = (reason) => {
// 只有pending状态才能转换
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
// 执行所有失败回调
this.onRejectedCallbacks.forEach(fn => fn());
}
};
// 执行executor,捕获异常
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// then方法
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) => {
// 如果状态已经是fulfilled
if (this.status === FULFILLED) {
// 使用setTimeout模拟微任务
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
// 如果状态已经是rejected
if (this.status === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
// 如果状态还是pending,将回调存入队列
if (this.status === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise2;
}
// catch方法
catch(onRejected) {
return this.then(null, onRejected);
}
// 静态resolve方法
static resolve(value) {
return new MyPromise((resolve) => {
resolve(value);
});
}
// 静态reject方法
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
}
// Promise解析函数
function resolvePromise(promise2, x, resolve, reject) {
// 防止循环引用
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected'));
}
// 如果x是Promise实例
if (x instanceof MyPromise) {
x.then(resolve, reject);
} else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
// 如果x是对象或函数
let called = false;
try {
const then = x.then;
if (typeof then === 'function') {
// 如果then是函数,认为x是thenable对象
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 (error) {
if (called) return;
called = true;
reject(error);
}
} else {
// 普通值直接resolve
resolve(x);
}
}
使用示例
// 示例1:基本使用
const promise1 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('成功');
}, 1000);
});
promise1.then(
value => {
console.log(value); // 1秒后输出:成功
return '第二次处理';
}
).then(
value => {
console.log(value); // 输出:第二次处理
}
);
// 示例2:错误处理
const promise2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject('失败原因');
}, 1000);
});
promise2
.then(value => {
console.log(value);
})
.catch(error => {
console.log('捕获错误:', error); // 输出:捕获错误: 失败原因
});
// 示例3:链式调用
new MyPromise((resolve) => {
resolve(1);
})
.then(value => {
console.log(value); // 输出:1
return value + 1;
})
.then(value => {
console.log(value); // 输出:2
return value + 1;
})
.then(value => {
console.log(value); // 输出:3
});
// 示例4:返回Promise
new MyPromise((resolve) => {
resolve(1);
})
.then(value => {
return new MyPromise((resolve) => {
setTimeout(() => {
resolve(value * 2);
}, 1000);
});
})
.then(value => {
console.log(value); // 1秒后输出:2
});
// 示例5:静态方法
MyPromise.resolve('直接成功').then(value => {
console.log(value); // 输出:直接成功
});
MyPromise.reject('直接失败').catch(error => {
console.log(error); // 输出:直接失败
});
关键点
- 状态管理:Promise有三种状态(pending、fulfilled、rejected),状态只能从pending转换为fulfilled或rejected,且不可逆
- 回调队列:使用数组存储then方法注册的回调函数,支持同一个Promise多次调用then
- 异步执行:使用setTimeout模拟微任务,确保then回调异步执行
- 链式调用:then方法返回新的Promise实例,实现链式调用
- 值穿透:当then方法参数不是函数时,实现值的向下传递
- Promise解析:resolvePromise函数处理then回调返回值,支持返回普通值、Promise实例或thenable对象
- 循环引用检测:防止then回调返回自身Promise导致的死循环
- 错误处理:捕获executor和回调函数执行过程中的异常,通过reject传递
- 参数校验:确保onFulfilled和onRejected是函数类型,提供默认实现
- 静态方法:实现Promise.resolve和Promise.reject快捷方法
目录