手动实现 Promise
Posted NsNe
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手动实现 Promise相关的知识,希望对你有一定的参考价值。
Promise
代表了一个异步操作的最终完成或者失败
定义状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
构造函数定义
function MyPromise(excutor){
// 初始状态为 pending
this.status = PENDING;
// 成功的值
this.value = undefined;
// 失败的原因
this.reason = undefined;
// then 的回调函数集合,后面会用到
this.fulfilledCallback = [];
this.rejectedCallback = [];
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
// 状态变更后执行 then 的回调函数
this.fulfilledCallback.forEach(fn => fn(value))
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.rejectedCallback.forEach(fn => fn(reason))
}
}
try {
excutor(resolve, reject);
} catch (error) {
reject(error);
}
}
原型方法
MyPromise.prototype.then = function(onResolve, onReject){
onResolve = onResolve === undefined ? value => value : onResolve,
onReject = onReject === undefined ? error => { throw error } : onReject;
return new MyPromise((resolve, reject) => {
function handle(func, value){
try {
const result = func(value);
// 如果返回一个 Promise
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (err) {
reject(err);
}
}
if (this.status === FULFILLED) {
queueMicrotask(() => {
handle(onResolve, this.value);
});
}
if (this.status === REJECTED) {
queueMicrotask(() => {
handle(onReject, this.reason);
});
}
// 状态为 pending,将回调函数保存到前面定义的函数集合中
if (this.status === PENDING) {
// 保存到 fulfilledCallback
this.fulfilledCallback.push(value => {
queueMicrotask(() => {
handle(onResolve, value);
});
});
// 保存到 rejectedCallback
this.rejectedCallback.push(reason => {
queueMicrotask(() => {
handle(onReject, reason)
});
});
}
})
};
MyPromise.prototype.catch = function (onReject) {
return this.then(undefined, onReject);
};
MyPromise.prototype.finally = function (cb) {
return this.then(
(value) => MyPromise.resolve(cb()).then(() => value),
(reason) =>
MyPromise.resolve(cb()).then(() => {
throw reason;
})
);
};
静态方法
MyPromise.resolve = function (value) {
// 如果参数是MyPromise实例,直接返回这个实例
if (value instanceof MyPromise) return value;
return new MyPromise((resolve) => resolve(value));
};
MyPromise.reject = function (value) {
// 如果参数是MyPromise实例,直接返回这个实例
if (value instanceof MyPromise) return value;
return new MyPromise((resolve, reject) => reject(value));
};
MyPromise.race = function (promises) {
return new Promise((resolve, reject) => {
promises.forEach((p) => {
MyPromise.resolve(p).then(resolve, reject);
});
});
};
MyPromise.all = function (promises) {
let result = [];
const len = promises.length;
let count = 0;
return new MyPromise((resolve, reject) => {
promises.forEach((p, index) => {
MyPromise.resolve(p).then(
(res) => {
result[index] = res;
count++;
if (count === len) {
resolve(result);
}
},
(error) => {
reject(error);
}
);
});
});
};
MyPromise.allSettled = function (promises) {
let result = [];
const len = promises.length;
let count = 0;
return new MyPromise((resolve, reject) => {
promises.forEach((p, index) => {
MyPromise.resolve(p).then(
(value) => {
result[index] = {
status: FULFILLED,
value,
};
count++;
if (count === len) {
resolve(result);
}
},
(reason) => {
result[index] = {
status: REJECTED,
reason,
};
count++;
if (count === len) {
resolve(result);
}
}
);
});
});
};
最后的最后
上述代码用到了queueMicrotask()
来执行微任务
mdn上也提供了queueMicrotask()
的polyfill实现
它通过使用立即 resolve 的 promise 创建一个微任务(microtask)
如下:
if (typeof window.queueMicrotask !== "function") {
window.queueMicrotask = function (callback) {
Promise.resolve()
.then(callback)
.catch(e => setTimeout(() => { throw e; }));
};
}
以上是关于手动实现 Promise的主要内容,如果未能解决你的问题,请参考以下文章