实现了Promise所有实例方法和静态方法(不考虑边界情况),其实主要是then的实现。
1.写完感觉自己对函数编程有了新的认识,刚开始还是有点绕的,各种回调,彻底掌握then函数后就感觉很妙。
2.对Promise也是知其然知其所以然。
// 定义状态
const STATUS_PENDING = 'pending';
const STATUS_FULFILLED = 'fulfilled';
const STATUS_REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
this.status = STATUS_PENDING;
this.onFulfilledFns = [];
this.onRejectedFns = [];
this.value = undefined;
this.reason = undefined;
const resolve = value => {
// 状态控制
if (this.status === STATUS_PENDING) {
this.status = STATUS_FULFILLED;
this.value = value;
// 开启微任务事件
queueMicrotask(() => {
// 执行then方法接收的回调函数,并回传参数
this.onFulfilledFns.forEach(fn => fn(value));
});
}
};
const reject = reason => {
if (this.status === STATUS_PENDING) {
this.status = STATUS_FULFILLED;
this.reason = reason;
queueMicrotask(() => {
this.onRejectedFns.forEach(fn => fn(reason));
});
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
// 默认值设置,兼容链式调用
const defaultFulfilled = () => {
return this.value;
};
const defaultRejected = () => {
// 通过抛出异常触发失败捕获
throw this.reason;
};
onFulfilled = onFulfilled ?? defaultFulfilled;
onRejected = onRejected ?? defaultRejected;
// 默认返回一个新的promise,支持链式调用
return new MyPromise((resolve, reject) => {
// 成功的回调收集
this.onFulfilledFns.push(value => {
// 将执行结果传递下去,且处理异常
try {
const res = onFulfilled(value);
resolve(res);
} catch (error) {
reject(error);
}
});
// 失败的回调收集
this.onRejectedFns.push(reason => {
try {
const res = onRejected(reason);
resolve(res);
} catch (error) {
reject(error);
}
});
});
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
finally(onFinally) {
// 调用resolve/reject都会最终执行
return this.then(onFinally, onFinally);
}
// promise静态方法 - 6个
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) => {
const values = [];
promises.forEach(p => {
p.then(
res => {
values.push(res);
if (values.length === promises.length) {
// 所有都成功时才返回resolve
resolve(values);
}
},
// 有一个失败直接reject
reject
);
});
});
}
// 所有promise都变更状态后返回resolve
static allSettled(promises) {
return new MyPromise(resolve => {
const values = [];
promises.forEach(p => {
p.then(res => {
values.push({ status: STATUS_FULFILLED, value: res });
if (values.length === promises.length) resolve(values);
}).catch(err => {
values.push({ status: STATUS_REJECTED, reason: err });
if (values.length === promises.length) resolve(values);
});
});
});
}
// 当任何一个promise变更状态时,返回对应res/rej
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(p => p.then(resolve, reject));
});
}
// 等待一个resolve,如果全部都是reject则返回AggregateError错误
static any(promises) {
return new MyPromise((resolve, reject) => {
const reasons = [];
promises.forEach(p => {
p.then(resolve).catch(err => {
reasons.push(err);
if (reasons.length === promises.length) {
reject(new AggregateError(reasons));
}
});
});
});
}
}
// test 实例方法
// const promise = new MyPromise((resolve, reject) => {
// setTimeout(() => {
// resolve({ name: 'xdl' });
// reject('err');
// }, 1000);
// // throw new Error('promise err');
// });
// promise
// .catch(err => {
// console.log('err', err);
// // return '123';
// throw 'err 111111';
// })
// .then(res => {
// console.log('res', res);
// })
// .catch(err => {
// console.log('err2', err);
// })
// .then(res => {
// console.log('res2', res);
// throw 'err 333333';
// })
// .catch(err => {
// console.log('err3', err);
// })
// .finally(() => {
// console.log('finally');
// throw 'err';
// })
// .then(
// res => {
// console.log('---res', res);
// },
// err => {
// console.log('---err', err);
// }
// );
// promise.catch(err => {
// console.log('p2 err', err);
// });
// promise.then(res => {
// console.log('p3 res:', res);
// });
// promise.then(res => {
// console.log('p4 res:', res);
// });
// test 静态方法
// MyPromise.resolve('success').then(res => console.log('res', res));
// MyPromise.reject('failed').catch(err => console.log('err', err));
const p1 = new MyPromise((res, rej) => {
setTimeout(() => {
rej('p1');
}, 3000);
});
const p2 = new MyPromise((res, rej) => {
setTimeout(() => {
rej('p2');
}, 2000);
});
const p3 = new MyPromise((res, rej) => {
setTimeout(() => {
res('p3');
}, 3000);
});
// MyPromise.all([p1, p2, p3])
// .then(res => {
// console.log('res', res);
// })
// .catch(err => {
// console.log('err', err);
// });
// MyPromise.allSettled([p1, p2, p3])
// .then(res => {
// console.log('res', res);
// })
// .catch(err => {
// console.log('err', err);
// });
MyPromise.any([p1, p2, p3])
.then(res => {
console.log('res', res);
})
.catch(err => {
console.log('err', err.errors, err.name);
});