• wordpress CMS主题:ssmay主题 wordpress CMS主题:ssmay主题
  • 首页 > 前端开发 > 你也可以手写自己的Promise(一)

    你也可以手写自己的Promise(一)

    作者: 分类:前端开发 点击: 1,014 次
    wordpress CMS主题:ssmay主题

      扫描下面的二维码,“关注”我的百家号。

      我写这篇文章不打算介绍Promise产生的原因以及它解决的问题,我只是想写一篇关于实现自己Promise的文章。如果代码以及逻辑有什么不对的地方,请大家指出来。就这些,开始正题。

      前提:我们要知道Promise是基于Promises/A+规范的。其中好多变量和方法名都是从这里来的。
      我们先从Promise的使用开始,写几个测试例子。

      let promise = new Promise((resolve, reject) =>{
          // console.log("1");
          // resolve("成功");
          // reject("失败");
          // console.log("2");// 第一步
      
      
          // reject("失败");
          // resolve("成功");// 第二步
      
          // setTimeout(() => {
          //     resolve("success");
          // }, 2000);
      
          throw new Error("手动抛出错误");// 第四步
      });
      promise.then((value) => {
          console.log("then第一个方法:"+value);
      }, (err) => {
          console.log("then第二个方法:"+err);
      })
      promise.then((value) => {
          console.log("then第一个方法:"+value);
      }, (err) => {
          console.log("then第二个方法:"+err);
      })
      console.log("3");
      

      第一步输出

      • 1
      • 2
      • 3
      • then第一个方法:成功
      • then第一个方法:成功

      第二步输出

      • 3
      • then第二个方法:失败
      • then第二个方法:失败

      第三步输出

      • 3
        两秒之后
      • then第一个方法:success
      • then第一个方法:success

      第四步输出

      • 3
      • then第二个方法:Error: 手动抛出错误
      • then第二个方法:Error: 手动抛出错误

      最后输出“成功”说明 then是异步执行的

      根据以上几个例子我们可以推出以下几点内容:

      • Promise是一个构造函数(使用了 new)
      • Promise接收一个参数,并且这个参数是一个函数(为了方便描述,我们称之为 executor)
      • executor在 new Promise时执行
      • new Promise中可以支持异步行为(第三步)
      • executor有两个参数(resolve,reject)
      • resolve和reject不会我们传进去的,说明是属于Promise内容提供的
      • resolve和reject都是函数,并且都接收一个参数。看规范:resolve接收参数称之为value,reject接收参数称之为reason
      • 每个Promise实例上都有then方法
      • then方法是异步的
      • then方法中有两个参数onFulfilled和onRejected 分别是成功的回调(执行resolve)和失败的回调(执行reject)。看这里
      • 一个Promise中resolve和reject只会执行一个,规范中有提到 Promise States,大家可以看下
      • 同一个promise的实例可以then多次,成功时回调用所有的成功方法,失败时回调用所有的失败方法
      • 如果发现错误就会走入失败态

      这么一大坨东西,看着有点乱。我们就根据我们得出的结论开始写属于自己的Promise。写的过程中思路慢慢就清晰了。

      let myPromise = function (executor) {
          let self = this;//缓存一下this
      
          self.status = 'pending';// 状态管理 状态的变化只能由pending变为resolved或者rejected。一件事情不能既成功又失败。所以resolved和rejected不能相互转化。
          self.value = undefined;// 成功后的值 传给resolve
          self.reason = undefined;//失败原因 传给reject
      
          self.onResolvedCallbacks = [];// 存放then中成功的回调
          self.onRejectedCallbacks = []; // 存放then中失败的回调 
          // 这里说明一下,第三步使用定时器。执行完 new Promise 之后,会执行then方法,此时会把then中的方法缓存起来,并不执行:此时状态还是pending。等到定时器2秒之后,执行
          // resolve|reject 时,而是依次执行存放在数组中的方法。 参考发布订阅模式
      
          function resolve(value) {
              // pending => resolved
              if (self.status === 'pending') {
                  self.value = value;
                  self.status = 'resolved';
                  // 依次执行缓存的成功的回调
                  self.onResolvedCallbacks.forEach(fn => fn(self.value));
              }
          }
      
          function reject(reason) {
              // pending => rejected
              if (self.status === 'pending') {
                  self.value = value;
                  self.status = 'rejected';
                  // 依次执行缓存的失败的回调
                  self.onRejectedCallbacks.forEach(fn => fn(self.reason));
              }
          }
      
          try {
              //new Promise 时 executor执行
              executor(resolve, reject);
          } catch (error) {
              reject(error);// 当executor中执行有异常时,直接执行reject
          }
      }
      
      // 每个Promise实例上都有then方法
      Promise.prototype.then = function (onFulfilled, onRejected) {
          let self = this;
      
          // 执行了 resolve
          if (self.status === 'resolved') {
              // 执行成功的回调
              onFulfilled(self.value);
          }
      
          // 执行了 reject
          if (self.status === 'rejected') {
              // 执行失败的回调
              onRejected(self.reason);
          }
      
          // new Promise中可以支持异步行为 当既不执行resolve又不执行reject时 状态是默认的等待态pending
          if (self.status === 'pending') {
              // 缓存成功的回调
              self.onResolvedCallbacks.push(onFulfilled);
              // 缓存失败的回调
              self.onRejectedCallbacks.push(onRejected);
          }
      };
      

      说明一下:这是最简版,因为Promise的强大之处是链式调用。我们这个只是雏形,由于时间关系。我们先到这里。下一次我们基于这个雏形实现符合Promises/A+规范的完整版。

      第一次发表文章,希望各位大虾多多支持。



      欢迎“关注”我的百家号。

      头条二维码
      加入我的QQ群
      头条二维码
      关注我的百家号

    文章作者:sunny
    本文地址:http://wanlimm.com/77202006218419.html
    版权所有 © 转载时必须以链接形式注明作者和原始出处!

    上一篇:
    下一篇:
    wordpress CMS主题:ssmay主题

    或许你会感兴趣的文章:

    发表评论

    您的电子邮箱地址不会被公开。 必填项已用*标注

    此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据