Promise
创建MyPromise类,通过es6中class.
- executor中有两个参数
- 两种执行回调,一种是成功回调resolve,一种是失败回调reject
class MyPromise {
constructor(executor) {
// 成功回调
const resolve = (value) => {};
// 失败回调
const reject = (reason) => {};
// 执行器立即执行resolve/reject
executor(resolve, reject);
}
}
Promise 中有三个状态: pending、fulfilled、rejected
- pending 初始状态,可以改变为fulfilled(成功)和rejected(失败)
- fulfilled 成功状态, 操作已成功,且有一个value 值
- rejected 拒绝状态,操作已失败,且有一个reason原因值
- promise 的状态只能改变一次,即改变之后都不会在改变
- promise 中有错误throw抛出的话相当于 rejected
class MyPromise {
static #PROMISE_STATUS_PENDING = "pending";
static #PROMISE_STATUS_FULFILLED = "fulfilled";
static #PROMISE_STATUS_REJECTED = "rejected";
constructor(executor) {
this.status = MyPromise.#PROMISE_STATUS_PENDING;
this.value = undefined;
this.reason = undefined;
// 成功回调
const resolve = (value) => {
if (this.status === MyPromise.#PROMISE_STATUS_PENDING) {}
};
// 失败回调
const reject = (reason) => {
if (this.status === MyPromise.#PROMISE_STATUS_PENDING) {}
};
// 执行器立即执行resolve/reject
executor(resolve, reject);
}
}
then
then 方法可以传入两个参数,当状态为fulfilled时执行,当状态为rejected时执行
class MyPromise {
static #PROMISE_STATUS_PENDING = "pending";
static #PROMISE_STATUS_FULFILLED = "fulfilled";
static #PROMISE_STATUS_REJECTED = "rejected";
constructor(executor) {...}
// then 方法 有两个参数 onFulfilled onRejected
then(onFulfilled, onRejected) {
// 状态为fulfilled,执行onFulfilled,传入成功的值
if (this.status === MyPromise.#PROMISE_STATUS_FULFILLED) {
onFulfilled(this.value);
}
// 状态为rejected,执行onRejected,传入失败原因
if (this.status === MyPromise.#PROMISE_STATUS_REJECTED) {
onRejected(this.reason);
}
}
}
异步问题,当resolve/reject在异步中执行时,当status还是pending初始状态应该将onFulfilled/onRejected成功或者失败回调存入数组中,等待状态改变,再调用他们.
- promise中then方法为微任务,可以使用queueMicrotask来模拟微任务
- 当同时调用resolve/reject时,会同时触发,因此要加不是pending状态时return出去
class MyPromise {
static #PROMISE_STATUS_PENDING = "pending";
static #PROMISE_STATUS_FULFILLED = "fulfilled";
static #PROMISE_STATUS_REJECTED = "rejected";
constructor(executor) {
this.status = MyPromise.#PROMISE_STATUS_PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledFns = [];
this.onRejectedFns = [];
const resolve = (value) => {
if (this.status === MyPromise.#PROMISE_STATUS_PENDING) {
// 微任务
queueMicrotask(() => {
// 加if判断不为pending不执行下面代码
if (this.status !== MyPromise.#PROMISE_STATUS_PENDING) return;
this.status = MyPromise.#PROMISE_STATUS_FULFILLED;
this.value = value;
this.onFulfilledFns.forEach((fn) => fn(this.value));
});
}
};
const reject = (reason) => {
if (this.status === MyPromise.#PROMISE_STATUS_PENDING) {
queueMicrotask(() => {
if (this.status !== MyPromise.#PROMISE_STATUS_PENDING) return;
this.status = MyPromise.#PROMISE_STATUS_REJECTED;
this.reason = reason;
this.onRejectedFns.forEach((fn) => fn(this.reason));
});
}
};
}
// then 方法 有两个参数 onFulfilled onRejected
then(onFulfilled, onRejected) {
// 状态为fulfilled,执行onFulfilled,传入成功的值
if (this.status === MyPromise.#PROMISE_STATUS_FULFILLED) {
onFulfilled(this.value);
}
// 状态为rejected,执行onRejected,传入失败的原因
if (this.status === MyPromise.#PROMISE_STATUS_REJECTED) {
onRejected(this.reason);
}
// status还是pending初始状态,存入对应数组中
if (this.status === MyPromise.#PROMISE_STATUS_PENDING) {
this.onFulfilledFns.push(onFulfilled(this.value));
this.onRejectedFns.push(onRejected(this.reason));
}
}
}
promise 常用的特点就是链式调用,解决回调地狱
- 在then里面返回新的promise,传递给下个then中
- 如果返回是一个普通值,直接传递给下个then
- 无论是在onFulfilled或者onRejected中返回都是传递给下个then中的onFulfilled里
- 只有抛出错误才会走onRejected里面
class MyPromise {
static #PROMISE_STATUS_PENDING = "pending";
static #PROMISE_STATUS_FULFILLED = "fulfilled";
static #PROMISE_STATUS_REJECTED = "rejected";
constructor(executor) {...}
// then 方法 有两个参数 onFulfilled onRejected
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
// 状态为fulfilled,执行onFulfilled,传入成功的值
if (this.status === MyPromise.#PROMISE_STATUS_FULFILLED) {
MyPromise.#catchFunctionExecutor(onFulfilled, this.value, resolve, reject);
}
// 状态为rejected,执行onRejected,传入失败的原因
if (this.status === MyPromise.#PROMISE_STATUS_REJECTED) {
MyPromise.#catchFunctionExecutor(onRejected, this.reason, resolve, reject);
}
// status还是pending初始状态,存入对应数组中
if (this.status === MyPromise.#PROMISE_STATUS_PENDING) {
this.onFulfilledFns.push(()=>{
MyPromise.#catchFunctionExecutor(onFulfilled, this.value, resolve, reject);
});
this.onRejectedFns.push(()=>{
MyPromise.#catchFunctionExecutor(onRejected, this.reason, resolve, reject);
});
}
})
}
// 错误捕获执行器
static #catchFunctionExecutor(method, value, resolve, reject) {
try {
const result = method(value);
resolve(result);
} catch (e) {
reject(e);
}
}
}
catch
promise中的catch也是捕获错误的一种,和then中的onRejected作用相当
- 当then中的参数只有onRejected时,我们需要在then中添加默认值,第一个值onFulfilled不传为undefined会影响我们调onFulfilled,因此加个默认值
class MyPromise {
static #PROMISE_STATUS_PENDING = "pending";
static #PROMISE_STATUS_FULFILLED = "fulfilled";
static #PROMISE_STATUS_REJECTED = "rejected";
constructor(executor) {...}
// then 方法 有两个参数 onFulfilled onRejected
then(onFulfilled, onRejected) {
const defaultOnFulfilled = (value) => value;
const defaultOnRejected = (error) => {throw error;};
onFulfilled ||= defaultOnFulfilled;
onRejected ||= defaultOnRejected;
return new MyPromise((resolve, reject) => {
// 状态为fulfilled,执行onFulfilled,传入成功的值
if (this.status === MyPromise.#PROMISE_STATUS_FULFILLED) {
MyPromise.#catchFunctionExecutor(onFulfilled, this.value, resolve, reject);
}
// 状态为rejected,执行onRejected,传入失败的原因
if (this.status === MyPromise.#PROMISE_STATUS_REJECTED) {
MyPromise.#catchFunctionExecutor(onRejected, this.reason, resolve, reject);
}
// status还是pending初始状态,存入对应数组中
if (this.status === MyPromise.#PROMISE_STATUS_PENDING) {
this.onFulfilledFns.push(()=>{
MyPromise.#catchFunctionExecutor(onFulfilled, this.value, resolve, reject);
});
this.onRejectedFns.push(()=>{
MyPromise.#catchFunctionExecutor(onRejected, this.reason, resolve, reject);
});
}
})
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
// 错误捕获执行器
static #catchFunctionExecutor(method, value, resolve, reject) {...}
}
finally
promise中的finally不论状态为成功还是失败都会执行
class MyPromise {
static #PROMISE_STATUS_PENDING = "pending";
static #PROMISE_STATUS_FULFILLED = "fulfilled";
static #PROMISE_STATUS_REJECTED = "rejected";
constructor(executor) {...}
// then 方法 有两个参数 onFulfilled onRejected
then(onFulfilled, onRejected) {...}
finally(onFinally) {
return this.then(onFinally, onFinally);
}
}
resolve
promise的静态方法resolve,默认执行resolve成功
static resolve(value) {
return new MyPromise((resolve) => resolve(value));
}
reject
promise的静态方法reject,默认执行reject失败
static reject(reason) {
return new MyPromise((resolve,reject) => reject(reason));
}
all / allSettled
promise的静态方法all/allSettled,传参为数组
- all 只有全为resolve时才会成功,有一个为reject直接reject
- allSettled 不管成功失败都会走resolve
- 返回值都是数组,且顺序一致
static all(promises) {
return new MyPromise((resolve, reject) => {
MyPromise.#createRangeGenerator("all", promises, resolve, reject);
});
}
static allSettled(promises) {
return new MyPromise((resolve, reject) => {
MyPromise.#createRangeGenerator("allSettled", promises, resolve, reject);
});
}
// 生成器自动化执行all/allSettled
// 采用生成器是模拟,当executor中都是不同时间返回值,插入数组的值就会按照快慢返回而错乱
static #createRangeGenerator(type, promises, resolve, reject) {
const result = [];
function* generator() {
yield* promises;
}
function execGeneratorFn(generatorFn) {
const genFn = generatorFn();
(function exec() {
const res = genFn.next();
if (res.done) return res.value;
if (type === "all") {
res.value.then((value) => {
result.push(value);
if (result.length === promises.length) resolve(result);
exec();
}, reject);
}
if (type === "allSettled") {
res.value.then(
(value) => {
result.push({ status: MyPromise.#PROMISE_STATUS_FULFILLED, value });
if (result.length === promises.length) resolve(result);
exec();
},
(reason) => {
result.push({ status: MyPromise.#PROMISE_STATUS_REJECTED, reason });
if (result.length === promises.length) resolve(result);
exec();
}
);
}
})();
}
execGeneratorFn(generator);
return result;
}
race / any
promise的静态方法rece/any,传参为数组
- rece 竞速传入多个promise,无论成功失败,只返回最快的一个
- any 只返回成功最快的一个,当全部为错误时,返回AggregateError报错
static race(promises){
return new MyPromise((resolve, reject) => {
promises.forEach(promise =>{
promise.then(resolve,reject)
})
});
}
static any(promises){
return new MyPromise((resolve, reject) => {
const result = []
promises.forEach(promise =>{
promise.then(resolve,reason=>{
result.push(reason)
if (result.length === promises.length){
reject(new AggregateError(result,"All promises were rejected"))
}
})
})
});
}
总结 :
class MyPromise {
static #PROMISE_STATUS_PENDING = "pending";
static #PROMISE_STATUS_FULFILLED = "fulfilled";
static #PROMISE_STATUS_REJECTED = "rejected";
constructor(executor) {
this.status = MyPromise.#PROMISE_STATUS_PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledFns = [];
this.onRejectedFns = [];
const resolve = (value) => {
if (this.status === MyPromise.#PROMISE_STATUS_PENDING) {
queueMicrotask(() => {
if (this.status !== MyPromise.#PROMISE_STATUS_PENDING) return;
this.status = MyPromise.#PROMISE_STATUS_FULFILLED;
this.value = value;
this.onFulfilledFns.forEach((fn) => fn(this.value));
});
}
};
const reject = (reason) => {
if (this.status === MyPromise.#PROMISE_STATUS_PENDING) {
queueMicrotask(() => {
if (this.status !== MyPromise.#PROMISE_STATUS_PENDING) return;
this.status = MyPromise.#PROMISE_STATUS_REJECTED;
this.reason = reason;
this.onRejectedFns.forEach((fn) => fn(this.reason));
});
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
const defaultOnFulfilled = (value) => value;
const defaultOnRejected = (error) => {
throw error;
};
onFulfilled ||= defaultOnFulfilled;
onRejected ||= defaultOnRejected;
return new MyPromise((resolve, reject) => {
if (this.status === MyPromise.#PROMISE_STATUS_FULFILLED) {
MyPromise.#catchFunctionExecutor(onFulfilled, this.value, resolve, reject);
}
if (this.status === MyPromise.#PROMISE_STATUS_REJECTED) {
MyPromise.#catchFunctionExecutor(onRejected, this.reason, resolve, reject);
}
if (this.status === MyPromise.#PROMISE_STATUS_PENDING) {
this.onFulfilledFns.push(() => {
MyPromise.#catchFunctionExecutor(onFulfilled, this.value, resolve, reject);
});
this.onRejectedFns.push(() => {
MyPromise.#catchFunctionExecutor(onRejected, this.reason, resolve, reject);
});
}
});
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
finally(onFinally) {
return this.then(onFinally, onFinally);
}
static resolve(value) {
return new MyPromise((resolve) => resolve(value));
}
static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason));
}
static all(promises) {
return new MyPromise((resolve, reject) => {
MyPromise.#createRangeGenerator("all", promises, resolve, reject);
});
}
static allSettled(promises) {
return new MyPromise((resolve, reject) => {
MyPromise.#createRangeGenerator("allSettled", promises, resolve, reject);
});
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach((promise) => {
promise.then(resolve, reject);
});
});
}
static any(promises) {
return new MyPromise((resolve, reject) => {
const result = [];
promises.forEach((promise) => {
promise.then(resolve, (reason) => {
result.push(reason);
if (result.length === promises.length) {
reject(new AggregateError(result, "All promises were rejected"));
}
});
});
});
}
// 生成器自动化执行all/allSettled
static #createRangeGenerator(type, promises, resolve, reject) {
const result = [];
function* generator() {
yield* promises;
}
function execGeneratorFn(generatorFn) {
const genFn = generatorFn();
(function exec() {
const res = genFn.next();
if (res.done) return res.value;
if (type === "all") {
res.value.then((value) => {
result.push(value);
if (result.length === promises.length) resolve(result);
exec();
}, reject);
}
if (type === "allSettled") {
res.value.then(
(value) => {
result.push({ status: MyPromise.#PROMISE_STATUS_FULFILLED, value });
if (result.length === promises.length) resolve(result);
exec();
},
(reason) => {
result.push({ status: MyPromise.#PROMISE_STATUS_REJECTED, reason });
if (result.length === promises.length) resolve(result);
exec();
}
);
}
})();
}
execGeneratorFn(generator);
return result;
}
// 错误捕获执行器
static #catchFunctionExecutor(method, value, resolve, reject) {
try {
const result = method(value);
resolve(result);
} catch (e) {
reject(e);
}
}
}
文章内容较长,如果表达有误在所难免,欢迎交流指出.