class MyPromise {
constructor(executor) {
this.status = 'pending'; // 初始状态为 pending
this.value = undefined; // Promise 的结果值
this.error = undefined; // Promise 的错误信息
this.onFulfilledCallbacks = []; // 存储 Promise 成功状态下的回调函数
this.onRejectedCallbacks = []; // 存储 Promise 失败状态下的回调函数
// 成功时执行的函数
const resolve = (value) => {
if (this.status === 'pending') {
if (value instanceof MyPromise) {
// 如果 value 的值是一个 Promise 对象,等其状态改变后再执行
value.then(resolve, reject);
}
}
if (isThenable(value)) {
// 如果 value 是一个 thenable 对象,那么就先把它转为 Promise 对象,然后等待它的状态改变
return handleThenable(value, resolve, reject);
}
this.status = 'fulfilled'; // 状态改变为 fulfilled
this.value = value; // 保存结果值
this.executeCallbacks(this.onFulfilledCallbacks); // 执行回调函数
}
// 失败时执行的函数
const reject = (error) => {
if (this.status === 'pending') {
this.status = 'rejected'; // 状态改变为 rejected
this.error = error; // 保存错误信息
this.executeCallbacks(this.onRejectedCallbacks); // 依次执行失败状态下的回调函数
}
}
try {
executor(resolve, reject); // 执行执行器函数,并传入 resolve 和 reject 函数作为参数
} catch (error) {
reject(error); // 捕获执行器函数中的错误,并将 Promise 状态改为 rejected
}
}
executeCallbacks(callbacks) {
callbacks.forEach((callback) => {
/*
* 为什么要使用 setTimeout 呢?
*
* 因为js的代码执行是基于时间循环的。当执行到一个宏任务(例如执行函数、网络请求等)时,会先执行当前任务的同步代码,然后再执行微任务队列中的任务。
* 在微任务队列中的任务执行完毕后,才会执行下一个宏任务。
*
* 而使用 setTimeout 时,会将函数的执行放到下一个宏任务中执行。将毁掉函数放入延时定时器中,设置为0秒的延时,实际上是将其放到了下一个宏任务中执行。
* 这样做的目的是为了确保当前的同步代码执行完毕,让js引擎有机会执行微任务队列中的任务,比米娜阻塞时间循环。
*
* 而在 executeCallbacks 函数中,我们是通过forEach遍历回调函数并执行的。使用延时定时器是为了将回调函数放到下一个宏任务中执行,确保当前Promise的状态已经改变,从而
* 能够正确的执行回调函数。
*
* */
setTimeout(() => {
try {
const result = callback(this.value);
if (result === this) {
// 如果回调函数返回的值是当前 Promise 对象,那么就会陷入死循环,这时需要抛出错误
throw new TypeError('Chaining cycle detected for promise #<Promise>');
}
if (isThenable(result)) {
// 如果回调函数返回的是一个 thenable 对象,那么就先把它转为 Promise 对象,然后等待它的状态改变
handleThenable(result, resolve, reject);
} else {
// 否则就是返回的是一个普通值,那么就用该值直接调用 resolve 函数,解析结果
resolve(result);
}
} catch (error) {
// 如果回调函数执行时抛出了异常,那么就用该异常对象调用 reject 函数,并将 Promise 状态改为 rejected
reject(error);
}
}, 0)
})
}
// then 方法
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value; // 如果 onFulfilled 不是函数,则将其设置为一个返回 value 的函数
onRejected = typeof onRejected === 'function' ? onRejected : (error) => { throw error }; // 如果 onRejected 不是函数,则将其设置为一个抛出 error 的函数
/*
*
* 每次调用 then 方法都会生成一个新的Promise对象,而不是修改原是的Promise对象。这时Promise链式调用的特性,保证了每个Promise对象的状态都是独立的,互不影响。
*
*/
return new MyPromise((resolve, reject)=>{
const fulfilledHandler = () => {
setTimeout(() => {
try {
// 如果 onFulfilled 返回的是一个 thenable 对象,那么就先把它转为 Promise 对象,然后等待它的状态改变
const result = onFulfilled(this.value);
if (isThenable(result)) {
handleThenable(result, resolve, reject); // 如果 onFulfilled 返回的是一个 thenable 对象,那么就先把它转为 Promise 对象,然后等待它的状态改变
} else {
resolve(result); // 否则就是返回的是一个普通值,那么就用该值直接调用 resolve 函数,解析结果
}
} catch (error) {
reject(error); // 如果 onFulfilled 执行时抛出了异常,那么就用该异常对象调用 reject 函数,并将 Promise 状态改为 rejected
}
}, 0)
}
const rejectedHandler = () => {
setTimeout(() => {
try {
const result = onRejected(this.error); // 如果 onRejected 执行时抛出了异常,那么就用该异常对象调用 reject 函数,并将 Promise 状态改为 rejected
if (isThenable(result)) {
handleThenable(result, resolve, reject); // 如果 onRejected 返回的是一个 thenable 对象,那么就先把它转为 Promise 对象,然后等待它的状态改变
} else {
resolve(result); // 否则就是返回的是一个普通值,那么就用该值直接调用 resolve 函数,解析结果
}
} catch (error) {
reject(error); // 如果 onRejected 执行时抛出了异常,那么就用该异常对象调用 reject 函数,并将 Promise 状态改为 rejected
}
}, 0)
}
if (this.status === 'fulfilled') {
fulfilledHandler(); // 如果当前 Promise 的状态是 fulfilled,那么就执行 onFulfilled 函数
} else if (this.status === 'rejected') {
rejectedHandler(); // 如果当前 Promise 的状态是 rejected,那么就执行 onRejected 函数
} else {
this.onFulfilledCallbacks.push(fulfilledHandler); // 存储成功状态下的回调函数
this.onRejectedCallbacks.push(rejectedHandler); // 存储失败状态下的回调函数
}
})
}
// catch 方法
catch(onRejected) {
return this.then(undefined, onRejected); // 指定失败回调函数
}
// finally 方法
finally(onFinally) {
return this.then(
(value) => MyPromise.resolve(onFinally()).then(() => value), // 执行 finally 回调函数后,继续返回 Promise 的值
(error) => MyPromise.resolve(onFinally()).then(() => { throw error }) // 执行 finally 回调函数后,继续抛出错误
)
}
// 静态 resolve 方法
static resolve(value) {
// 如果参数是 Promise 实例,那么直接返回这个实例
if (value instanceof MyPromise) {
return value; // 如果参数是 Promise 实例,那么直接返回这个实例
}
// 如果参数是 thenable 对象,那么就先将其转为 Promise 对象,然后等待它的状态改变
if (isThenable(value)) {
return new MyPromise((resolve, reject) => {
handleThenable(value, resolve, reject); // 如果参数是 thenable 对象,那么就先将其转为 Promise 对象,然后等待它的状态改变
})
}
return new MyPromise((resolve) => resolve(value)); // 如果参数是普通值,那么直接返回以该值为成功状态的 Promise 对象
}
// 静态 reject 方法
static reject(error) {
return new MyPromise((resolve, reject) => reject(error)); // 直接返回以该错误对象为失败状态的 Promise 对象
}
// 静态 all 方法
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = []; // 存储所有 Promise 的结果
let completedCound = 0; // 记录已经完成的 Promise 的数量
const checkCompletion = () => {
if (completedCound === promises.length) {
resolve(results); // 当所有 Promise 都完成时,调用 resolve 函数
}
}
// 遍历所有 Promise
promises.forEach((promises, index) => {
// 如果当前 Promise 的状态是 fulfilled,那么就将其结果存入 result 数组中
promises.then((value) => {
results[index] = value; // 将 Promise 的结果存入 result 数组中
completedCound++; // 已经完成的 Promise 的数量加 1
checkCompletion(); // 检查是否所有 Promise 都已经完成
}).catch((error) => {
reject(error); // 如果有任何一个 Promise 失败,则将错误信息传递给 reject 函数
})
})
})
}
// 静态race方法
static race(promises) {
return new MyPromise((resolve, reject)=>{
// 遍历所有 Promise
promises.forEach((promise)=>{
// 如果当前 Promise 的状态是 fulfilled,那么就将其结果存入 result 数组中
promise.then((value)=>{
resolve(value); // 如果有任何一个 Promise 成功,则将其结果传递给 resolve 函数
}).catch((error)=>{
reject(error); // 如果有任何一个 Promise 失败,则将错误信息传递给 reject 函数
})
})
})
}
}
// 判断一个对象是否是 thenable 对象
function isThenable(value) {
return value && typeof value.then === 'function'; // 判断一个对象是否是 thenable 对象
}
// 处理 thenable 对象
function handleThenable(thenable, resolve, reject) {
try {
thenable.then(resolve, reject); // 如果参数是 thenable 对象,那么就先将其转为 Promise 对象,然后等待它的状态改变
} catch (error) {
reject(error); // 如果在处理过程中出现错误,则将错误信息传递给 reject 函数
}
}