从入门到自定义Promise系列(三)——自定义Promise最简单描述、理解及实现

《尚硅谷Promise教程(promise前端进阶必学)》学习笔记

简单理解

HTML 页面内的异步任务(如:settimeout)用Promise包裹“托管”起来,不影响后面代码执行(js非阻塞);HTML页面内调用then或者catch方法,其实是将成功和失败的回调函数传递到Promise.js中;Promise.js存储HTML页面传递过来的回调函数,当页面内的异步任务结束后,调用 resolve 或 rejecte 方法,resolve 或 reject 方法执行事先存储的回调函数。

大致过程

  • HTML 页面中,Promise 用来包裹异步回调,then 方法是同步执行
    • then 方法的调用传入成功和失败的回调函数,用以Promise模块存储;
    • Promise 内包裹的异步回调中调用 resolve 或 rejecte 方法
  • Promise.js 模块,resolve 或 rejecte 方法调用
    • resolve 或 rejecte 方法改变状态
    • resolve 或 rejecte 方法执行一开始 HTML 同步执行时候传递到Promise模块存储起来的回调函数

具体实现

JavaScript 部分

/**
 * 自定义Promise函数 模块
 * ES5中模块定义方法:匿名函数自调用(或者自调用函数表达式或者函数表达式自调用)即IIFE
 */
(function (window) {
  /**
   * Promise构造函数
   * excutor:执行器函数(同步执行)
   */
  function Promise(excutor) {
    //1、构造函数实现
    //1.7构造函数测试——将当前promise对象保存起来,存储self
    const self = this;

    //1.3思考promise实例对象有怎样的属性?
    //1.3.1存储状态的属性(给promise对象指定status属性,初始值为pending)
    self.status = "pending";
    //1.3.2存储数据结果值的属性(给给promise对象指定一个用于存储结果数据的属性)
    self.data = undefined;
    //1.3.3存储回调函数,每个元素的结构:{onResolved(){},onRejected(){}}
    self.callbacks = [];

    function resolve(value) {
      //1.2定义resolve和reject两个方法
      //1.5 还有一个问题,不能反复的resolve,思考如果当前状态不是pending,直接结束,如何限制状态只改一次
      if (self.status !== "pending") {
        return;
      }

      //1.4思考执行resolve和reject方法需要做什么?
      //1.4.1将状态改为resolved
      self.status = "resolved";
      //1.4.2保存value数据
      self.data = value;

      /**
       * 1.4.3调用resolve的时候可能已经指定了回调函数,如果有待执行的callback函数,异步执行回调,放入回调队列
       * 立即异步执行回调函数onResolved
       * callbackObj为包含两个回调函数的对象
       * 回调函数放入到队列中,使用settimeout函数模拟
       */
      if (self.callbacks.length > 0) {
        // callbackObj.onResolved();//这样还是同步,未放入队列中
        setTimeout(() => {
          //模拟异步回调,放入队列中,执行所有成功回调
          self.callbacks.forEach((callbacksObj) => {
            callbacksObj.onResolved(value); //调用成功的回调,怎么能不传参数呢
          });
        });
      }
    }

    function reject(reason) {
      //1.3两函数形参value和reason
      if (self.status !== "pending") {
        return;
      }
      self.status = "rejected";
      self.data = reason;
      if (self.callbacks.length > 0) {
        setTimeout(() => {
          self.callbacks.forEach((callbacksObj) => {
            callbacksObj.onRejected(reason);
          });
        });
      }
    }

    //1.6既没调resolve也没调rejecte,执行器抛出异常,promise状态变为失败,有抛出异常就有捕获异常
    try {
      excutor(resolve, reject); //1.1立即同步执行执行器,需要传入两参数
    } catch (error) {
      //如果执行器抛出异常,promise对象变为rejected
      reject(error);
    }
  }
  /**
   * Promise原型对象的then()
   * 指定成功和失败的回调函数
   * 返回一个新的Promise对象
   */
  Promise.prototype.then = function (onResolved, onRejected) {
    /**
     * 最简单实现
     * 假设当前状态还是pending状态,不能执行回调函数,
     * 状态不由.then来改,只能把两个回调函数存储起来
     */
    const self = this;
    self.callbacks.push({
      onResolved,
      onRejected,
    });
  };

  /**
   * Promise原型对象的catch()
   * 指定失败的回调函数
   * 返回一个新的Promise对象
   */
  Promise.prototype.catch = function (onRejected) {};
  /**
   * Promise函数对象方法 resolve()
   * 返回一个指定结果的成功的promise
   */
  Promise.resolve = function (value) {};
  /**
   * Promise函数对象方法reject()
   * 返回一个指定reason的失败的promise
   */
  Promise.reject = function (reason) {};
  /**
   * Promise函数对象的all方法
   * 返回一个promise,只有当所有promise都成功时才成功,否则只要有一个失败的就失败
   */
  Promise.all = function (promises) {};
  /**
   * Promise函数对象的race方法
   * 返回一个promise,其结果由第一个完成的promise决定
   */
  Promise.race = function (promises) {};

  //向外暴露Promise函数
  window.Promise = Promise;
})(window);

HTML 部分

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义Promise</title>
</head>

<body>
    <ol>
        <li>1、自定义Promise——Promise整体框架</li>
        <li>2、自定义Promise——Promise构造函数实现</li>
    </ol>
    <script src="./lib/Promise.js"></script>
    <script>
        const p = new Promise((resolve, reject) => {
            setTimeout(() => {
                // resolve(1);//value//1.测试成功
                reject(2);//reason//2测试失败
                //下面log语句先执行,后面then方法里的回调后执行才验证时异步执行
                console.log('reject改变状态');//测试是同步还是异步???
            }, 100);
        });
        p.then(value => {
            console.log('onResolved()1', value);
        }, reason => {
            console.log('onReject()1', reason);
        });
        p.then(value => {
            console.log('onResolved()2', value);
        }, reason => {
            console.log('onReject()2', reason);
        });
    </script>
</body>

</html>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值