Promise的实现

98 阅读3分钟

我报名参加金石计划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为p1then返回的新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+文档加深理解。