封装Promise需要注意的问题:
- 一个promise对象可能有多个then,catch回调,确定状态以后需要遍历所有的回调函数进行执行。
- then或catch回调可能在定时器中添加,如果此时确定了状态,则直接执行即可。
- 实现then,catch的连续调用,则在then中没有传入onRejected回调时,自定义onRejected回调,将error抛出,交给下面的catch执行。
//状态常量
const PROMISE_STATUS_PENDING = "pending";
const PROMISE_STATUS_FULFILLED = "fulfilled";
const PROMISE_STATUS_REJECTED = "rejected";
//封装try/catch函数,用于执行onFulfilled或onRejected
function TryWitchCatchFn(exefn, value, resolve, reject) {
try {
const result = exefn(value);
resolve(result);
} catch (error) {
reject(error);
}
}
//封装Promise类
class LzPromise {
//传入exector回调函数
constructor(exector) {
this.status = PROMISE_STATUS_PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledFns = [];
this.onRejectedFns = [];
const resolve = (value) => {
if (this.status == PROMISE_STATUS_PENDING) {
queueMicrotask(() => {
//执行微任务之前要判断状态时pending
if (this.status !== PROMISE_STATUS_PENDING) return;
this.status = PROMISE_STATUS_FULFILLED;
this.value = value;
this.onFulfilledFns.forEach((fn) => {
fn();
});
});
}
};
const reject = (reason) => {
if (this.status == PROMISE_STATUS_PENDING) {
queueMicrotask(() => {
//执行微任务之前要判断状态时pending
if (this.status !== PROMISE_STATUS_PENDING) return;
this.status = PROMISE_STATUS_REJECTED;
this.reason = reason;
this.onRejectedFns.forEach((fn) => {
fn();
});
});
}
};
//接受传入的两个回调函数参数
try {
exector(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
//如果then没有传入onRejected函数,则将错误抛出,交给cath方法处理
onRejected =
onRejected ||
((err) => {
throw err;
});
onFulfilled =
onFulfilled ||
((value) => {
return value;
});
//默认返回一个Promise对象
return new LzPromise((resolve, reject) => {
//如果状态已经确定
//如,在定时器中添加then(),那么此时状态已经确定,执行执行回调即可
if (this.status === PROMISE_STATUS_FULFILLED) {
TryWitchCatchFn(onFulfilled, this.value, resolve, reject);
}
//如果有状态,直接执行
if (this.status === PROMISE_STATUS_REJECTED) {
TryWitchCatchFn(onFulfilled, this.reason, resolve, reject);
}
//如果为Pending状态,则添加到数组当中
if (this.status === PROMISE_STATUS_PENDING) {
this.onFulfilledFns.push(() => {
TryWitchCatchFn(onFulfilled, this.value, resolve, reject);
});
this.onRejectedFns.push(() => {
TryWitchCatchFn(onRejected, this.reason, resolve, reject);
});
}
});
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
finally(onFinally) {
this.then(
() => {
onFinally();
},
(err) => {
onFinally();
}
);
}
static resolve(value) {
return new LzPromise((resolve, reject) => {
resolve(value);
});
}
static reject(value) {
return new LzPromise((resolve, reject) => {
reject(value);
});
}
static all(promises) {
return new LzPromise((resolve, reject) => {
let values = [];
promises.forEach((promise) => {
promise.then(
(res) => {
values.push(res);
//所有的promise都返回结果再执行resolve
if (values.length === promises.length) {
resolve(values);
}
},
(err) => {
//有err直接返回
reject(err);
}
);
});
});
}
static allSettled(promises) {
return new LzPromise((resolve, reject) => {
let resultOjb = [];
promises.forEach((promise) => {
promise.then(
(res) => {
resultOjb.push({status: PROMISE_STATUS_FULFILLED, value: res});
if (resultOjb.length === promises.length) {
resolve(resultOjb);
}
},
(err) => {
resultOjb.push({status: PROMISE_STATUS_REJECTED, value: err});
if (resultOjb.length === promises.length) {
resolve(resultOjb);
}
}
);
});
});
}
//只要有一个返回结果就结束,不管是fulfiled,还是rejected状态
static race(promises) {
return new LzPromise((resolve, reject) => {
promises.forEach((promise) => {
promise.then(
(res) => {
resolve(res);
},
(err) => {
reject(err);
}
);
});
});
}
//等到以fulfiled结果后才返回,所有都是rejected时,抛出固定错误
static any(promises) {
return new LzPromise((resolve, reject) => {
let reasons = [];
promises.forEach((promise) => {
promise.then(
(res) => {
resolve(res);
},
(err) => {
reasons.push(err);
if (reasons.length === promises.length) {
reject(new AggregateError(reasons));
}
}
);
});
});
}
}
更多好文移步龙仔的个人博客(longzai1024.top/home ),谢谢关注!