手写Promise

promise的状态

为什么会出现Promise?

promise是为了解决回调地狱问题。回调函数本身是很优秀的但是,当业务一多就会造成业务逻辑复杂,业务逻辑复杂造成回调增多,层层嵌套,形成了回调地狱造成代码可观赏性降低,维护成本增高。目前promise是最好的异步处理方案,所以来学一下promise。

回调地狱 => 业务逻辑复杂 => 回调增多 => 可维护性,观赏性降低

promise 有三个状态:pending(等待中), fulfilled(成功), rejected(失败),

打个比方说我有一个承诺十年后去实现,不是现在实现是十年后(异步)

  // 定义isPromise :true/false我是否实现了承诺
      let isPromise = false;

我许下了一个承诺 => (异步) 比如:'我十年后我会去娶她'

承诺有两个结果:一个是实现了承诺(resolve),一个是没有实现承诺(reject)

 // 我许下了一个承诺 => (异步) 比如:'我十年后我会去娶她'
 // 承诺有两个结果:实现了承诺(resolve),没有实现承诺(reject)
 //定义一个承诺出来    
 let getPromise = new Promise((resolve, reject) => {
 //判断是否完成了承诺,如果完成调用resolve表示成功,如果没有完成承诺调用reject表示拒绝
        if (isPromise) {
          let promise_z = {
            tip: "我记得有一个承诺",
            result: "我实现了承诺",
          };
          // 完成了承诺
          resolve(promise_z);
        } else {
          let err = new Error(
            "我有一个承诺,但是因为某些原因我违背了我的承诺,对不起"
          );
          reject(err);
        }
      });

接下来测试一下我有没有去实现承诺

     let testFn = function () {
        getPromise
          .then((fulfilled) => {
            console.log(fulfilled.tip, fulfilled.result);
          })
          .catch((rejected) => {
            console.log(rejected.message);
          });
      };
      testFn();

如果isPromise=true实现承诺会调用.then方法显示:我记得有一个承诺我实现了承诺

如果isPromise=false没有实现承诺会调用.catch方法显示:我有一个承诺,但是因为某些原因我违背了我的承诺,对不起

所以通过上面会发现

打个比方 :你和你的女朋友在交往,一旦你承诺你后面会娶她,就只有两个结果,在过程中是女方等待(pending)的过程,但是她最后只能得到你的一种回复要么是成功(fulfilled),要么是失败(rejected),没有可能是你没说过这句话,说出去的话泼出去的水一样,收不回来。

promise是异步它的状态无法改变因为最开始的状态是pending(等待中),一旦执行就只有一个结果成功(fulfilled)或者失败(rejected)

应用层promise的链式调用

接下来再接着上面的例子写,打个比方你要娶你的女朋友,那么你们会结婚,但是如果你不想娶你的女朋友你们就不会结婚

还是和刚才一样

先承诺会去娶她

    // isPromise :true/false我是否实现了承诺
      let isPromise = true;
      // 我许下了一个承诺 => (异步) 比如:'我十年后我会去娶她'
      // 承诺有两个结果:实现了承诺(resolve),没有实现承诺(reject)
      let getPromise = new Promise((resolve, reject) => {
        if (isPromise) {
          let promise_z = {
            tip: "我记得有一个承诺",
            result: "我实现了承诺",
          };
          // 完成了承诺
          resolve(promise_z);
        } else {
          let err = new Error(
            "我有一个承诺,但是因为某些原因我违背了我的承诺,对不起"
          );
          reject(err);
        }
      });

然后再声明一个你们会结婚,前提是你记得承诺会去娶她,里面声明了一个msg是消息

      // 我在实现承诺说要娶她后,才会和她结婚,如果不说娶她,就不会和她结婚
      let getMarry = (promise_z) => {
        let marry = {
          tip: "我和她说我要娶她",
          result: "我们要结婚了",
        };
        let msg = {
          message: marry.tip + marry.result,
          marry: marry,
          promise_z: promise_z,
        };
        return Promise.resolve(msg);
      };

其次再测试一下有没有去实现承诺,在第一个then里面传了一个promise对象,当第一个承诺实现后,会接着嗲用第二个承诺,因为是链式调用最后先得到结婚,然后再得到实现了之前的承诺

      let testFn2 = () => {
        getPromise
          .then(getMarry) //传的是promise对象
          .then((fulfilled) => {
            console.log(fulfilled);
          })
          .catch((rejected) => {
            console.log(rejected.message);
          });
      };
      testFn2();

手写Promise的链式调用 ES5

从pending到fulfilled

 promise的状态从pending(等待)=》成功通过resolve返回值 =》状态变为 fulfilled(成功)

从pending到rejected

 promise的状态从pending(等待)=》失败通过reject抛出错误 =》状态变为 rejected(失败)

从四个方面入手

1、基本结构

2、then方法

3、支持异步

4、链式调用

   <script>
      //1、基本结构
      // excutor 用来指向的
      function myPromise(excutor) {
        let self = this;
        self.status = "pending"; //状态
        self.value = null; //成功之后,返回数据
        self.reason = null; //失败的原因

        //7、解决异步问题   =》暂存区
        // 发布订阅者模式先将相关的值存起来,当状态变化的时候再将里面的状态一个一个的取出
        self.onFulfilledCallbacks = [];
        self.onRejectedCallbacks = [];

        // 返回成功的结果
        function resolve(value) {
          // 5.1 更改成功状态
          if (self.status === "pending") {
            self.value = value; //保存成功结果
            self.status = "fulfilled";

            // 9、状态改变 =》 依次取出
            self.onFulfilledCallbacks.forEach((item) => item(value));
          }
        }

        // 返回失败的原因
        function reject(reason) {
          // 5.2更改失败状态
          if (self.status === "pending") {
            self.reason = reason; //失败原因
            self.status = "rejected";

            // 9、状态改变 =》 依次取出
            self.onRejectedCallbacks.forEach((item) => item(reason));
          }
        }

        // 3、excutor => 立即执行
        // excutor && excutor(resolve, reject);
        // try catch 是为了做容错处理
        try {
          excutor(resolve, reject);
        } catch (err) {
          reject(err);
        }
      }

      // 2、then()方法 放在原型上 不管成功还是失败都会走进来
      myPromise.prototype.then = function (onFulfilled, onRejected) {
        // 6. 确保传进来的是方法,如果不是,定义一个方法
        onFulfilled =
          typeof onFulfilled === "function"
            ? onFulfilled
            : function (data) {
                resolve(data);
              };
        // 判断函数是不是方法(类型是不是 function)如果不是就写个方法 抛出错误
        onRejected =
          typeof onRejected === "function"
            ? onRejected
            : function (err) {
                throw err;
              };

        let self = this;
        //8、 暂存回调函数
        if (self.status === "pending") {
          self.onFulfilledCallbacks.push(onFulfilled);
          self.onRejectedCallbacks.push(onRejected);
        }

        // if (self.status === "fulfilled") {
        //   return new myPromise((resolve, reject) => {
        //     try {
        //       let x = onFulfilled(selef.value);
        //       x instanceof myPromise ? x.then(resolv, reject) : resolve(x);
        //     } catch (err) {
        //       reject(err);
        //     }
        //   });
        // }
      };

      //3、初级嗲用
      let demo = new myPromise((resolve, reject) => {
        console.log("111");

        // 异步任务
        // 如果没写相关代码,在异步任务中执行resolve函数是没用的因为状态没变更.then方法没法调用,所以需要用到发布订阅者模式
        setTimeout(() => {
          resolve(222);
        }, 2000);
      });
      demo.then((data) => console.log(data));
    </script>

上面代码,关于链式调用的还没写,其它的完成了

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值