自定义实现Promise功能(笔记)

手写Promise

个人学习笔记,不保证全部正确,参考即可

大纲

  • 对象属性
    1.状态:status
    2.数据:data
    3.回调函数的数组:callbacks
  • 构造函数内部的方法
    1.resolve //传给回调函数调用,改变Promise的状态,status:“resolved”
    2.reject //传给回调函数调用,改变Promise的状态,status:“rejected”
  • 原型上的方法
    1.then //返回一个新的Promise对象,实现链式调用,根据回调函数中return的值改变新Promise的状态
    2.catch //返回一个新的Promise对象,新Promise状态改为失败(rejected)
  • 函数对象的方法
    1.resolve //返回一个新的Promise,新Promise状态根据return的内容而定
    2.reject //返回一个新的Promise,新Promise状态改为失败(rejected)
    3.all
    4.race
(function (window) {

  // 状态常量
  const PENDING = 'pending';
  const RESOLVED = 'resolved';
  const REJECTED = 'rejected';

  /*
  Promise构造函数
  resolve方法
  reject方法
  */ 
  function Promise (excutor) {
    // 保存this
    const that = this;

    that.status = PENDING;  // Promise的状态
    that.data = undefined;  // 存放数据
    that.callbacks = [];  // 存放预先指定的回调函数

    // 成功时调用
    function resolve (value) {
      if(that.status !== PENDING){
        return;
      }
      // 改变状态
      that.status = RESOLVED;
      // 存放数据
      that.data = value;
      // 判断是否是先指定了回调函数,是就执行数组中的回调函数
      if (that.callbacks.length > 0) {
        setTimeout(() => {
          that.callbacks.forEach(callbackObj => {
            callbackObj.onResolved(value);
          });
        })
      }
    }

    // 失败时调用
    function reject (reason) {
      if(that.status !== PENDING){
        return;
      }
      // 改变状态
      that.status = REJECTED;
      // 存放数据
      that.data = reason;
      // 判断是否是先指定了回调函数,是就执行数组中的回调函数
      if (that.callbacks.length > 0) {
        setTimeout(() => {
          that.callbacks.forEach(callbackObj => {
            callbackObj.onRejected(reason);
          });
        })
      }
    }

    // 捕获异常,应对throw的情况
    try{
      // 调用执行器,将resolve和reject方法传入
      excutor(resolve, reject);
    } catch (err) {
      // 如果直接抛出异常,就调用reject
      reject(err)
    }
  }

  /*
  原型中的then,处理成功和失败的回调函数
  返回一个新的Promise,实现链式调用
  异常穿透
  */
  Promise.prototype.then = function (onResolved, onRejected){
    // 保存this
    const that = this;

    // 预防没写回调函数,都变为函数
    onResolved = typeof onResolved === 'function' ? onResolved : value => value;
    // 异常穿透
    onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}

    // 返回一个新的Promise,实现链式调用
    return new Promise((resolve, reject) => {
      // handle处理回调函数中return的结果
      function handle (callback) {
        try{
          // 得到回调函数的结果
          const result = callback(that.data);
          // 如果回调结果为Promise
          if(result instanceof Promise){
            result.then(resolve, reject)
          } else {
            // 否则就直接传值给下一个then
            resolve(result);
          }
        } catch (err) {
          // 如果回调函数中的return是throw异常,就直接调用下一个then的失败回调函数
          reject(err);
        }
      }

      // 根据当前Promise的状态,异步处理对应的回调函数,并处理新Promise的状态,以便下一个then进行回调
      if (that.status === RESOLVED) {
        // setTimeout是为了加入js回调栈中,实现异步处理
        setTimeout(() => {
          handle(onResolved);
        })
      } else if (that.status === REJECTED) {
        setTimeout(() => {
          handle(onRejected);
        })
      } else {  // 如果当前状态是pending,说明是先指定了回调函数,要把回调函数放入数组中
        that.callbacks.push({
          onResolved (value) {
            handle(onResolved);
          },
          onRejected (reason) {
            handle(onRejected);
          }
        })
      }


    })
  }

  /*
  原型中的catch,处理失败的回调函数
  返回一个新的Promise
  */
  Promise.prototype.catch = function (onRejected){
    return this.then(undefined, onRejected);
  }

  /*
  resolve方法,返回成功的Promise,或者失败的Promise
  */
  Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
      if(value instanceof Promise){  // 如果是Promise,返回该Promise的结果
        value.then(resolve, reject);
      } else {  //如果是值,就直接返回成功的Promise
        resolve(value);
      }
    })
  }

  /*
  reject方法,返回失败的Promise
  */
  Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
      reject(reason);
    })    
  }

  /*
  Promise函数对象方法all
  返回一个新的Promise
  所有的Promise成功才返回成功的Promise,否则返回失败的Promise
  值的顺序不能乱
  */
  Promise.all = function (promises) {
    // 保存成功的value值
    const values = new Array(promises.length);
    // 记录成功的promise数
    let resolveCount = 0;
    return new Promise((resolve, reject) => {
      promises.forEach((p, index) => {
        Promise.resolve(p).then(
          value => {
            values[index] = value;
            // 数量加1
            resolveCount ++;
            // 判断是否已经全部成功,是就返回成功的Promise
            if(resolveCount === promises.length){
              resolve(values)
            }
          },

          // 如果有一个失败,就返回失败的Promise
          reason => {
            reject(reason)
          }
        )
      })
    })
  }

  /*
  Promise函数对象方法race
  返回一个新的Promise
  所有的Promise成功才返回成功的Promise,否则返回失败的Promise
  值的顺序由执行时间来决定
  */
  Promise.race = function (promises) {
   // 保存成功的value值
   const values = new Array(promises.length);
   // 记录成功的promise数
   let resolveCount = 0;
   return new Promise((resolve, reject) => {
     promises.forEach((p, index) => {
       // Promise.resolve(p)的作用是将数组中不是Promise对象的元素也编程Promise对象
       Promise.resolve(p).then(  
         value => {
            resolve(value)
         },
         // 如果有一个失败,就返回失败的Promise
         reason => {
           reject(reason)
         }
       )
     })
   })
  }

  //暴露Promise
  window.Promise = Promise;
})(window)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值