Appearance
手写Promise实现,遵循Promise/A+规范
TIP
这是手动实现Promise的过程,遵循Promise/A+规范,并附带注释。 Promises/A+规范与ECMAScript中promise有些许不同,在事件执行顺序上有一些差异,所以手动实现的promise与nodejs和V8引擎中执行promise结果会有差异。具体差异可查看文章 V8 promise源码解读https://juejin.cn/post/7055202073511460895
javascript
// 状态常量,promise的三种状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
#state = PENDING;//状态
#value = undefined;//传递给resolve的值
#reason = undefined;//传递给reject的原因
#onFulfilledCallbacks = [];//then的onFulfilled回调函数,因为then可以连续调用,onFulfilled可能有多个
#onRejectedCallbacks = [];//then的onRejected回调函数,因为catch可以连续调用,onRejected可能有多个
//promise的构造函数,executor是一个函数,接收两个参数resolve和reject,分别用于传递成功和失败的值
//executor函数在promise实例化时立即执行,用于初始化promise的状态和执行异步操作
constructor(executor) {
// 如果executor不是函数,则抛出类型错误
if (typeof executor !== "function") {
throw new TypeError(
`Promise resolver ${executor ? Object.prototype.toString.call(executor) : executor} is not a function`,
);
}
/**
* 定义resolve和reject函数,用于传递成功和失败的值
* 并将状态设置为fulfilled或rejected,并执行对应的回调函数
*/
const resolve = (value) => {
// 如果状态已经是fulfilled或rejected,则忽略;因为promise状态一旦变化,则不能再次改变
if (this.#state === PENDING) {
// queueMicrotask是将函数放到下一个微任务中执行
queueMicrotask(() => {
if (this.#state !== PENDING) return;// 不要把this.#state !== PENDING和上方this.#state === PENDING弄混淆了,这里并不冲突,因为微任务是异步执行的
this.#state = FULFILLED;
this.#value = value;
this.#onFulfilledCallbacks.forEach((cb) => cb());
});
}
};
const reject = (reason) => {
if (this.#state === PENDING) {
queueMicrotask(() => {
if (this.#state !== PENDING) return;
this.#state = REJECTED;
this.#reason = reason;
this.#onRejectedCallbacks.forEach((cb) => cb());
});
}
};
// 执行executor函数,需要把执行错误抛出,不要忘记try catch
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// then方法,用于添加成功和失败的回调函数,返回一个新的promise实例
// 成功的回调函数接收成功的值,失败的回调函数接收失败的原因
// 成功的回调函数和失败的回调函数返回的值,会作为参数,传递给下一个then的回调函数
// 如果返回值是一个promise实例,则会等待这个promise实例状态改变,然后将结果传递给下一个then的回调函数
then(onFulfilled, onRejected) {
// onFulfilled和onRejected可以不传,但是then和catch可以链式调用,需要将promise值或者错误透传
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected = typeof onRejected === "function" ? onRejected : (err) => { throw err; };
// then方法需要返回一个新的promise实例,用于链式调用
return new MyPromise((resolve, reject) => {
const fulfilledHandler = () => {
try {
// 如果onFulfilled返回的是一个promise实例,则等待这个promise实例状态改变,然后将结果传递给下一个then的回调函数
const result = onFulfilled(this.#value);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (e) {
reject(e);
}
};
const rejectedHandler = () => {
try {
// 如果onRejected返回的是一个promise实例,则等待这个promise实例状态改变,然后将结果传递给下一个then的回调函数
const result = onRejected(this.#reason);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (e) {
reject(e);
}
};
if (this.#state === FULFILLED) {
// 如果状态是fulfilled,则立即执行成功的回调函数
queueMicrotask(fulfilledHandler);
} else if (this.#state === REJECTED) {
// 如果状态是rejected,则立即执行失败的回调函数
queueMicrotask(rejectedHandler);
} else if (this.#state === PENDING) {
// promise的状态是pending,则将成功和失败的回调函数添加到数组中,等待状态改变时执行
this.#onFulfilledCallbacks.push(fulfilledHandler);
this.#onRejectedCallbacks.push(rejectedHandler);
}
});
}
// catch方法,用于添加失败的回调函数,返回一个新的promise实例
// 失败的回调函数接收失败的原因,返回值会作为参数,传递给下一个then的回调函数
catch(onRejected) {
return this.then(undefined, onRejected);
}
// finally方法,用于添加一个回调函数,无论promise状态如何,都会执行这个回调函数
// 返回值会作为参数,传递给下一个then的回调函数
finally(onFinally) {
return this.then(
(value) => {
onFinally();
return value;
},
(reason) => {
onFinally();
throw reason;
},
);
}
// static方法,用于创建promise实例
static resolve(value) {
return new MyPromise((resolve) => resolve(value));
}
// static方法,用于创建失败的promise实例
static reject(err) {
return new MyPromise((_, reject) => reject(err));
}
// static all方法接收一个promise数组,返回一个新的promise实例,所有promise全部成功才成功,有一个失败则失败
static all(promiseArray) {
return new MyPromise((resolve, reject) => {
const result = [];
let count = 0;
const len = promiseArray.length;
if (len === 0) {
resolve(result);
return;
}
promiseArray.forEach((promise, index) => {
MyPromise.resolve(promise).then(
(value) => {
result[index] = value;
count++;
if (count === len) {
resolve(result);
}
},
(err) => {
reject(err);
},
);
});
});
}
// static allSettled方法接收一个promise数组,返回一个新的promise实例,无论promise状态如何,都会返回一个对象数组,包含状态和值
static allSettled(promiseArray) {
return new MyPromise((resolve) => {
const result = [];
let count = 0;
const len = promiseArray.length;
if (len === 0) {
resolve(result);
return;
}
promiseArray.forEach((promise, index) => {
MyPromise.resolve(promise).then(
(value) => {
result[index] = { status: FULFILLED, value };
count++;
if (count === len) {
resolve(result);
}
},
(reason) => {
result[index] = { status: REJECTED, reason };
count++;
if (count === len) {
resolve(result);
}
},
);
});
});
}
// static any方法接收一个promise数组,返回一个新的promise实例,只要有一个promise成功,则成功,全部失败则失败
// 失败的原因是一个AggregateError实例,包含所有失败的原因
static any(promiseArray) {
return new MyPromise((resolve, reject) => {
const reason = [];
let count = 0;
const len = promiseArray.length;
if (len === 0) {
reject(new AggregateError(reason));
return;
}
promiseArray.forEach((promise, index) => {
MyPromise.resolve(promise).then(
(value) => {
resolve(value);
},
(err) => {
reason[index] = err;
count++;
if (count === len) {
reject(new AggregateError(reason));
}
},
);
});
});
}
// static race方法接收一个promise数组,返回一个新的promise实例,只要有一个promise成功,则成功,全部失败则失败
static race(promiseArray) {
return new MyPromise((resolve, reject) => {
promiseArray.forEach((promise) => {
MyPromise.resolve(promise).then(resolve, reject);
});
});
}
}