我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第n篇文章,点击查看活动详情
上一节写了Promise的简单使用,这一节我们来根据我们的使用来实现一下Promise。
Promise的实现文章有很多,我们写简易一点,这边贴一个很好的文章:剖析Promise内部结构,一步一步实现一个完整的、能通过所有Test case的Promise类
先贴上最终的代码:
function myPro(extuc) {
var self = this;
// 保存this的引用
this.data = "";
// dat为resolve传入的值,
self.ResolveBack = [];
//数组是因为一个promise的多个子then方法,来让他们都被执行
// resolve的执行函数
const resolve = (value) => {
setTimeout(() => {
// 延时后改变值
// 将函数集都调用就可以了
this.data = value;
self.ResolveBack.forEach((back) => {
back(value);
});
});
};
// 将resolve函数传回去,由new promise的userPromise来调用
extuc(resolve);
}
// then方法,在原型上添加
myPro.prototype.then = function (onResolveBack) {
var self = this;
// 返回一个新的Promise
return new myPro((resolve) => {
// 往函数集力压入函数
self.ResolveBack.push(() => {
// 获取res
const res = onResolveBack(self.data);
if (res instanceof myPro) {
// 依旧时将执行交给userPromise的then方法
// 当userPromise执行resolve之后后面的链式调用才会执行
res.then(resolve);
} else {
// 一个值的话就resolve,依次执行onResolveBack里面的函数
resolve(res);
}
});
});
};
主要需要实现的点都实现了,我们看看使用的案例:
new myPro((resolve) => {
setTimeout(() => {
resolve("sucess with myPro");
}, 2000);
}).then((res) => {
console.log(res + " ending");
// 在这里输出最后的结果
return new myPro((resolve, reject) => {
resolve(res);
});
});
new myPro((resolve) => {
setTimeout(() => {
resolve("sucess with myPro");
}, 2000);
}).then((res) => {
return res + "ending";
});
写两个案例是对应
if (res instanceof myPro) {
res.then(resolve);
} else {
resolve(res);
}
这也是链式调用实现的地方,整段代码这个地方比较难以理解,我本人也是饶了很久,所以单独说一说。
可以看到在then方法中我们可以不返回任何东西,也可以返回值或者一个新的Promise,一般我们称new Promise为p1,then返回的新Promise为p2,然后用户在then中自己写的返回的Promise为userPromise
再来看下面的代码,这段代码一定是在p1它resolve之后才会继续执行下去,在这个push前面的代码则前面就已经同步执行了,这是基于EventLoop的原理,settimeout时一个宏任务,而这里push是在这个宏任务上添加微任务,所以这段代码会在resolve完成后才会执行。这很重要!!!也是难以理解的地方,建议多看看eventLoop,帮助理解。
self.ResolveBack.push(() => {
const res = onResolveBack(self.data);
if (res instanceof myPro) {
res.then(resolve);
} else {
resolve(res);
}
});
在理解了push的执行阶段就简单多了,onResolveBack的执行也就是then的执行变成了异步的执行。得到返回的res后,res当为Promise时,那么在userPromise执行resolve后,就会异步的执行这里的resolve方法,达到异步的效果。而如果返回的是一个值,那么就更简单了,直接resolve就可以了,不需要异步。
以上就是我对Peomise的简单实现,主要难在异步的实现,链式调用。 当然Promise实际还有很多内容,比如reject的情况,还有判断状态为resolve,reject,而在判断状态时状态又为padding(因为eventLoop,作为微任务的改变状态未执行)如何处理,异常处理,抛错等等,建议大家可以看看PromiseA+文档加深理解。