一、什么是Promise
在Promise A+规范中规定,Promise是一个有一个符合规范的then方法的对象或者函数。
1.关于then
- then接收onFulfilled和onRejected两个可选参数;
- then必须返回一个新的Promise对象;
- 如果onFulfilled是一个函数
- 在状态切换为fulfilled之后调用;
- 不能被多次调用。
- 如果onRejected是一个函数
- 在状态切换为rejected是被调用;
- 不能被多次调用。
2.状态
- pending: 初始状态,会转换为下面的俩个状态;
- fulfilled: 成功状态,不会再转为其他状态;
- rejected: 失败状态,不会再转为其他状态。
3.关于ES6中的Promise
- 构造函数接受一个回调函数executor;
- executor接受两个参数resolve、reject;
- executor在new Promise是被同步调用;
- 任务被解决时,调用resolve,并传入结果;
- 任务被拒绝时,调用reject,并传入拒绝原因;
- Promise对象除了then还有catch和finally两个函数;
- Promise有all、resolve等静态函数。
二、实现
1.状态定义
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
2.功能实现
class MyPromise {
// 当前状态
#state = PENDING;
// 解决或拒绝的结果
#result = undefined;
// 通关连环then注册的回调
#handlers = [];
// 构造函数
constructor(executor) {
// 定义两个状态切换函数
const resolve = (data) => {
this.#setState(FULFILLED, data);
};
const reject = (reason) => {
this.#setState(REJECTED, reason);
};
// 同步调用参数函数
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 状态切换
#setState(state, result) {
if (this.#state !== PENDING) return;
this.#state = state;
this.#result = result;
this.#run();
}
// 执行then注册的所有任务
#run() {
if (this.#state === PENDING) return;
// 遍历所有注册的回调
while(this.#handlers.length > 0){
const handler = this.#handlers.shift();
const {resolve, reject, onFulfilled, onRejected} = handler;
// 根据结果执行每个任务
if (this.#state === FULFILLED) {
this.#runOne(onFulfilled, resolve, reject);
} else if (this.#state === REJECTED) {
this.#runOne(onRejected, resolve, reject);
}
}
}
// 执行一个任务
#runOne() {
// 将任务放入微队列,等待被执行
this.#runMicroTask(() => {
if (typeof callback !== 'function') {
// 不是函数的话,透传一下当前结果
if (this.#state === FULFILLED) {
resolve(this.#result);
} else {
reject(this.#result);
}
return;
}
try {
const data = callback(this.#result);
if (this.#isPromiseLike(data)) {
// 结果是Priomise的话
data.then(resolve, reject);
} else {
// 不是Promise的话直接完成,并传递结果
resolve(data);
}
} catch (error) {
reject(error);
}
});
}
// 按Promise A+规范判断参数是否是一个Promise
#isPromiseLike(value) {
if (value !== null && (typeof value === 'object' || typeof value === 'function')) {
return typeof value.then === 'function';
}
return false;
}
// 将任务放入微队列
#runMicroTask(func) {
if (typeof process === 'object' && typeof process.nextTick === 'function') {
// 在nodejs中
process.nextTick(func);
} else if (typeof MutationObserver === 'function') {
// 在浏览器中
const textNode = document.createTextNode('1');
const ob = new MutationObserver(func);
// 让ob观察textNode的字符串变化,观察到之后会将构造函数
// 中传入的func加入微队列执行
ob.observe(textNode, {
characterData: true,
});
textNode.data = '2';
} else {
// 没有上述环境,只能用宏队列代替了
setTimeout(func, 0);
}
}
then(onFulfilled, onRejected) {
// 返回新Promise
return new MyPromise((resolve, reject) => {
// 将任务存起来
this.#handlers.push({
resolve,
reject,
onFulfilled,
onRejected,
});
this.#run();
});
}
}