<script>
// 定义三个常量表示promise的状态
const PROMISE_STATUS_PENDING = "pending";
const PROMISE_STATUS_FULFILLED = "fulfilled";
const PROMISE_STATUS_REJECTED = "reject";
// 封装工具函数
function execFunctionWithCatchError(execFn, value, resovle, reject) {
try {
const result = execFn(value);
resovle(result);
} catch (err) {
reject(err);
}
}
class HYPromise {
constructor(executor) {
this.status = PROMISE_STATUS_PENDING;
// 保存并传递值给then
this.value = undefined;
this.reason = undefined;
this.onFulfilledFns = [];
this.onRejectedFns = [];
const resolve = (value) => {
if (this.status === PROMISE_STATUS_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATUS_PENDING) return;
this.status = PROMISE_STATUS_FULFILLED;
this.value = value;
this.onFulfilledFns.forEach((fn) => {
fn();
});
// 执行传入then的第一个回调函数
});
}
};
const reject = (reason) => {
if (this.status === PROMISE_STATUS_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATUS_PENDING) return;
this.status = PROMISE_STATUS_REJECTED;
this.reason = reason;
this.onRejectedFns.forEach((fn) => {
fn();
});
// 执行传入then的第二个回调函数
});
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
// 利用抛错让下一个promise的catch帮忙处理
onRejected =
onRejected ||
((err) => {
throw err;
});
// 防止catch方法让链式调用断层
onFulfilled =
onFulfilled ||
((value) => {
return value;
});
return new HYPromise((resolve, reject) => {
// 如果在then调用的时候,状态已经确定下来
if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
execFunctionWithCatchError(
onFulfilled,
this.value,
resolve,
reject
);
}
if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
execFunctionWithCatchError(
onRejected,
this.reason,
resolve,
reject
);
}
// 将成功回调和失败回调放入对应的数组
if (this.status === PROMISE_STATUS_PENDING) {
if (onFulfilled) {
this.onFulfilledFns.push(() => {
execFunctionWithCatchError(
onFulfilled,
this.value,
resolve,
reject
);
});
}
if (onRejected) {
this.onRejectedFns.push(() => {
execFunctionWithCatchError(
onRejected,
this.reason,
resolve,
reject
);
});
}
}
});
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
finally(onFinally) {
this.then(
() => {
onFinally();
},
() => {
onFinally();
}
);
}
// 类方法
static resolve(value) {
return new HYPromise((resolve, reject) => {
resolve(value);
});
}
static reject(reason) {
return new HYPromise((resolve, reject) => {
reject(reason);
});
}
static all(promises) {
// 关键在什么时候执行resolve,什么时候执行reject
return new HYPromise((resolve, reject) => {
const values = [];
promises.forEach((promise) => {
promise.then(
(res) => {
values.push(res);
if (values.length === promises.length) {
resolve(values);
}
},
(err) => {
reject(err);
}
);
});
});
}
static allSettled(promises) {
return new HYPromise((resolve) => {
const results = [];
promises.forEach((promise) => {
promise.then(
(res) => {
results.push({
status: PROMISE_STATUS_FULFILLED,
vaule: res,
});
if (results.length === promises.length) {
resolve(results);
}
},
(err) => {
results.push({
stauts: PROMISE_STATUS_REJECTED,
reason: err,
});
if (results.length === promises.length) {
resolve(results);
}
}
);
});
});
}
static race(promises) {
return new HYPromise((resolve, reject) => {
promises.forEach((promise) => {
// promise.then((res) => {
// resolve(res),
// (err) => {
// resolve(err);
// };
// });
// 神来之笔的简化
promise.then(resolve, reject);
});
});
}
static any(promises) {
// resolve必须等到有一个成功的结果
// reject所有的都失败才执行reject
const reasons = [];
return new HYPromise((resolve, reject) => {
promises.forEach((promise) => {
promise.then(resolve, (err) => {
reasons.push(err);
if (reasons.length === promises.length) {
reject(new AggregateError(reasons));
}
});
});
});
}
}
// 实验
const p1 = new HYPromise((resolve, reject) => {
setTimeout(() => {
reject("111");
}, 1000);
});
const p2 = new HYPromise((resolve, reject) => {
setTimeout(() => {
reject("222");
}, 2000);
});
const p3 = new HYPromise((resolve, reject) => {
setTimeout(() => {
reject("333");
}, 3000);
});
HYPromise.any([p1, p2, p3])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
</script>
手写promise,包括类方法
最新推荐文章于 2024-02-19 09:17:52 发布