promise 是解决异步编程的一种方案,采用了状态编程的模式,通过注册 then 回调的方法,让异步代码可以一步一步执行,具体的细节请看代码:
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
class MyPromise {
constructor(callback) {
this.state = PENDING; // 定义 Promise 的状态,初始状态为 PENDING
this.value = undefined; // 存储 Promise 的结果值
this.callbacks = []; // 存储回调函数的数组
// resolve 函数用于将 Promise 的状态设置为 RESOLVED,并执行相应的回调函数
const resolve = (value) => {
if (this.state === PENDING) {
this.state = RESOLVED; // 将状态设置为 RESOLVED
this.value = value; // 存储 Promise 的结果值
this.scheduleCallbacks(); // 执行存储的回调函数
}
};
// reject 函数用于将 Promise 的状态设置为 REJECTED,并执行相应的回调函数
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED; // 将状态设置为 REJECTED
this.value = reason; // 存储 Promise 的结果值(错误原因)
this.scheduleCallbacks(); // 执行存储的回调函数
}
};
try {
callback(resolve, reject); // 执行用户传入的回调函数
} catch (err) {
reject(err); // 如果回调函数执行出错,则将 Promise 的状态设置为 REJECTED
}
}
// scheduleCallbacks 函数用于将回调函数的执行推迟到微任务队列中
scheduleCallbacks() {
queueMicrotask(() => {
this.callbacks.forEach(callback => {
this.executeCallback(callback);
});
});
}
// executeCallback 函数根据 Promise 的状态执行相应的回调函数
executeCallback(callback) {
const { onResolved, onRejected, resolve, reject } = callback;
if (this.state === RESOLVED) {
if (typeof onResolved === 'function') {
try {
const result = onResolved(this.value);
if (result instanceof MyPromise) result.then(resolve).catch(reject)
else resolve(result); // 将回调函数的返回值作为下一个 Promise 的结果值
} catch (error) {
reject(error); // 如果回调函数执行出错,则将 Promise 的状态设置为 REJECTED
}
} else {
resolve(this.value); // 如果没有传入回调函数,则将当前 Promise 的结果值传递给下一个 Promise
}
} else if (this.state === REJECTED) {
if (typeof onRejected === 'function') {
try {
const result = onRejected(this.value);
if (result instanceof MyPromise) result.then(resolve).catch(reject)
else resolve(result); // 将回调函数的返回值作为下一个 Promise 的结果值
} catch (error) {
reject(error); // 如果回调函数执行出错,则将 Promise 的状态设置为 REJECTED
}
} else {
reject(this.value); // 如果没有传入回调函数,则将当前 Promise 的结果值传递给下一个 Promise
}
}
}
// then 方法用于注册 Promise 的回调函数,并返回一个新的 Promise 对象
then(onResolved, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.state === PENDING) {
// 如果 Promise 的状态为 PENDING,则将回调函数和解决函数存储到 callbacks 数组中
this.callbacks.push({
onResolved,
onRejected,
resolve,
reject
});
} else {
// 如果 Promise 的状态已经变为 RESOLVED 或 REJECTED,则将回调函数推到微任务队列中执行
queueMicrotask(() => {
this.executeCallback({
onResolved,
onRejected,
resolve,
reject
});
});
}
});
}
// catch 方法用于注册 Promise 的错误回调函数,并返回一个新的 Promise 对象
catch(onRejected) {
return this.then(null, onRejected);
}
// 创建一个立即解决的 Promise 对象,并将指定的数据作为解决结果返回。
static resolve(data) {
return new MyPromise((resolve) => resolve(data));
}
// 创建一个立即拒绝的 Promise 对象,并将指定的原因作为拒绝结果返回。
static reject(reason) {
return new MyPromise((_, reject) => reject(reason));
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const result = [];
let resolvedCount = 0;
// 存储每个 Promise 的解决结果
promises.forEach((p, index) => {
p
.then((value) => {
result[index] = value;
resolvedCount++;
// 将解决的 Promise 结果存储到 result 数组中
resolvedCount === promises.length && resolve(result);
// 如果所有 Promise 都解决了,则将 result 数组作为解决结果返回
})
.catch(reject);
// 如果有任何一个 Promise 拒绝,则将整个 Promise 设置为拒绝状态
});
});
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach((p) => {
p.then(resolve).catch(reject);
// 只要有一个 Promise 解决或拒绝,就立即返回对应的结果
});
});
}
static allSettled(promises) {
return new MyPromise((resolve) => {
const results = [];
let settledCount = 0;
// 存储每个 Promise 的状态和结果
const allSettle = () => {
settledCount++;
// 统计已经处理完的 Promise 数量
settledCount === promises.length && resolve(results);
// 如果所有 Promise 都处理完了,则将 results 数组作为解决结果返回
};
promises.forEach((p, index) => {
p
.then((value) => {
results[index] = {
status: p.state,
value,
};
// 存储解决的 Promise 结果和状态
allSettle();
})
.catch((reason) => {
results[index] = {
status: p.state,
reason,
};
// 存储拒绝的 Promise 原因和状态
allSettle();
});
});
});
}
static any(promises) {
return new MyPromise((resolve, reject) => {
const reasons = [];
let rejectedCount = 0;
// 存储每个 Promise 的拒绝原因
promises.forEach((p, index) => {
p
.then(resolve)
.catch((reason) => {
reasons[index] = reason;
rejectedCount++;
// 存储拒绝的 Promise 原因
rejectedCount === promises.length && reject(reasons);
// 如果所有 Promise 都拒绝了,则将 reasons 数组作为拒绝结果返回
});
});
});
}
}