首先需要对Promise有哪些要点有一个掌握,具体的可以查看 Promises/A+规范中文版。
这里我列出几个手写简略版关注的点:
1. promise 是一个拥有 then
方法的对象或函数
1.1. then 方法接受两个参数:promise.then(onFulfilled, onRejected)
1.2 then 方法可以被同一个 promise 调用多次
1.3 then 方法必须返回一个 promise 对象
2. 一个 Promise 的当前状态必须为以下三种状态中的一种:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。并且只能有如下的变化关系,不可逆转:pending -> rejected | fulfilled
大致框架:
const Status = {
Pending: "pending",
Fulfilled: "fulfiied",
Rejected: "rejected"
}
class MyPromise {
constructor(executor) {
this.status = Status.Pending;
this.value = null;
this.reason = null;
// 成功的callback队列
this.fulfilledCb = [];
// 失败的callback队列
this.rejectedCb = [];
exec(this._resolve.bind(this), this._reject.bind(this));
}
_resolve(value) {
if (this.status === Status.Pending) {
this.value = value;
this.status = Status.Fulfilled;
// TODO: 依次执行fulfilledCb
}
}
_reject(reason) {
if (this.status === Status.Pending) {
this.reason = reason;
this.status = Status.Rejected;
// TODO: rejectedCb
}
}
then(onFulfilled, onRejected) {
}
}
链式调用
Promise的链式调用,就是可以一直.then().then()的调用,这是通过then方法返回一个新的promise实例来完成的,但是具体怎么和上一个promise连通的呢?我看了很多讲解,但是自己的脑回路是一团麻,理解起来还是有困难。把我的思路整理一下,大概是这样:
最后代码:
const Status = {
Pending: "pending",
Fulfilled: "fulfiied",
Rejected: "rejected"
};
class MyPromise {
constructor(exec) {
this.status = Status.Pending;
this.value = null;
this.reason = null;
this.fulfilledCb = [];
this.rejectedCb = [];
try {
exec(this._resolve.bind(this), this._reject.bind(this));
} catch (e) {
this._reject(e);
}
}
_runFulfilled() {
while (this.fulfilledCb.length) {
const cb = this.fulfilledCb.shift();
try {
var returnValue = cb.handler(this.value);
} catch (e) {
cb.nextPromise._reject(e);
}
if (returnValue instanceof MyPromise) {
returnValue
.then((v) => cb.nextPromise._resolve(v))
.catch((v) => cb.nextPromise._reject(v));
} else {
cb.nextPromise._resolve(returnValue);
}
}
}
_runRejected() {
while (this.rejectedCb.length) {
const cb = this.rejectedCb.shift();
try {
var returnValue = cb.handler(this.reason);
} catch (e) {
cb.nextPromise._reject(e);
}
if (returnValue instanceof MyPromise) {
returnValue
.then((v) => cb.nextPromise._resolve(v))
.catch((v) => cb.nextPromise._reject(v));
} else {
cb.nextPromise._resolve(returnValue);
}
}
}
_resolve(value) {
if (this.status === Status.Pending) {
this.value = value;
this.status = Status.Fulfilled;
this._runFulfilled();
}
}
_reject(reason) {
if (this.status === Status.Pending) {
this.reason = reason;
this.status = Status.Rejected;
this._runRejected();
while (this.fulfilledCb.length) {
const cb = this.fulfilledCb.shift();
cb.nextPromise._reject(reason);
}
}
}
then(onFulfilled, onRejected) {
const p = new MyPromise(() => {});
this.fulfilledCb.push({
handler: onFulfilled,
nextPromise: p
});
if (typeof onRejected === "function") {
this.rejectedCb.push({
handler: onRejected,
nextPromise: p
});
}
if (this.status === Status.Rejected) {
p._reject(this.reason);
}
if (this.status === Status.Fulfilled) {
this._runFulfilled();
}
return p;
}
catch(onRejected) {
const p = new MyPromise(() => {});
this.rejectedCb.push({
handler: onRejected,
nextPromise: p
});
if (this.status === Status.Rejected) {
this._runRejected();
}
return p;
}
}
module.exports = MyPromise;
codesandbox
Promise.all
Promise.myAll = (promiseArr) => {
const arr = Array.from(promiseArr)
const result = Array(arr.length)
const len = arr.length
let resolved = 0
return new Promise((resolve, reject) => {
arr.forEach((p, index) => {
Promise.resolve(p).then((res) => {
result[index] = res
if (++resolved === len) {
resolve(result)
}
}).catch(reject)
})
})
}
Promise.race
Promise.myRace = function (iterators) {
const promises = Array.from(iterators);
return new Promise((resolve, reject) => {
promises.forEach((promise, index) => {
Promise.resolve(promise).then(resolve).catch(reject);
});
});
};
Pomisify
const promisify = (fn, content) => {
return (...args) => {
return new Promise((resolve, reject) => {
const res = fn.apply(context, [...args, (err, data) => {
return err ? reject(err) : resolve(data)
}])
})
}
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!