用原生实现自己的Promise

(function(){
  // 实现Promise

function _Promise(fn){
  // 要求接收的fn必须是一个函数,否则报错
  if(typeof fn !== 'function') {
    throw new TypeError('_Promise resolver undefined is not a function')
  }
  // 每个实例应该有这两个属性:state,result
  this.state = 'pending'; // 初始状态为 pending
  this.result = undefined;  // 初始结果为 undefined

  // 事件池(自定义):这里存放的是then中传递的A函数和B函数
  this.eventPool = {
    A: function(){},
    B: function(){}
  }
  // 立即执行传递进来的fn函数:但是在执行fn的时候得给fn床底两个函数 resolev,reject
  var that = this;
  function resolve(res){ 
    // 这里接收一个参数,作为当前实例的result值
    // 执行这个函数的时候会将当前实例的状态从 pending转为 resolved
    /* if(that.state !== 'pending') return;
    that.state = 'resolved';
    that.result = res; */
    change('resolved', res)
  }
  function reject(rej){
    // 这里接收一个参数,作为当前实例的result值
    // 执行这个函数的时候会将当前实例的状态从 pending转为 rejected
   /*  if(that.state !== 'pending') return;
    that.state = 'rejected';
    that.result = rej; */
    change('rejected', rej)
  }
  // resolve函数和reject函数代码冗余,整合成一个
  function change(state, result){
    // 如果状态已经不是初始状态了,则直接退出,否则改变其状态和结果,并同时事件池中对应的函数执行
    if(that.state !== 'pending') return; 
    that.state = state;
    that.result = result;
    // 通知事件执行是异步的
    setTimeout(function(){
      that.state === 'resolved'? 
      // 这里可以监控到执行then中的方法的返回结果
      that.eventPool.A(that.result): 
      that.eventPool.B(result);
    })
  }
  // 注意:执行fn的时候,如果有报错,则当前实例的状态为失败,值为失败的原因
  try{
    fn(resolve, reject); 
  }catch(err){
    change('rejected', err);
  }
}

// _Promise的原型上有一个then方法,该方法接收两个函数A和B,根据实例的状态自动识别执行A还是B
/* _Promise.prototype.then = function(A, B){
  // this:当前_Promise的实例
  // A/B:是调用then的时候传递的两个函数

  // 如果参数不传递,则顺延
  if(typeof A !== 'function') {
    A = function(res){
      return _Promise.resolve(res);
    }
  }
  if(typeof B !== 'function') {
    B = function(rej) {
      return _Promise.reject(rej)
    }
  }
  this.eventPool.A = A;
  this.eventPool.B = B;
} */

// 给原型上扩展方法还可以这么写:注意补上constructor
_Promise.prototype = {
  constructor: _Promise,
  then: function(A, B){
    // this:当前_Promise的实例
    // A/B:是调用then的时候传递的两个函数
  
    // 如果参数不传递,则顺延
    if(typeof A !== 'function') {
      A = function(res){
        return _Promise.resolve(res);
      }
    }
    if(typeof B !== 'function') {
      B = function(rej) {
        return _Promise.reject(rej)
      }
    }
    /* this.eventPool.A = A;
    this.eventPool.B = B; */

   
    // 每次调用then方法都会返回一个新的实例
    var that = this;
    return new _Promise(function(resolve, reject){
      // resolve/reject函数执行是决定新实例的状态:可以通知then方法中对应的方法执行

      // 把传递进来的需要执行的A、B函数进行包装
      that.eventPool.A = function(res){
        // 进行监测:如果执行报错,返回的实例状态就为失败,值为失败的原因;否则就为成功,值为执行resolve是返回的结果
        try{
          var value = A(res);
          // 如果执行then的A方法返回的是一个新的_Promise实例,则这个新实例的状态和值直接决定返回实例的状态和值
          if(value instanceof _Promise){
            value.then(resolve, reject)
          }else{
            resolve(value);
          }
        }catch(err) {
          reject(err);
        }
      };
      that.eventPool.B = function(rej){
        try{
          var value = B(rej);
          if(value instanceof _Promise){
            value.then(resolve, reject)
          }else{
            resolve(value);
          }
        }catch(err) {
          reject(err);
        }
      }
    })
  },
  catch: function(B){
    // catch(B)方法等价于then(null, B)
    this.then(null, B);
  }
}

// 快速创建一个状态为成功的实例
_Promise.resolve = function(res) {
  return new _Promise(function(resolve){
    resolve(res)
  });
};

// 快速创建一个状态为失败的案例
_Promise.reject = function(res) {
  return new _Promise(function(undefined, reject){
    reject(res)
  });
};

_Promise.all = function(arr){
  return new _Promise(function(resolve, reject){
    var index = 0; // 计数用的
    var result = [];
    
    function success(){
      // 如果所有值都是成功的,则通知resolve执行
      if(index >= arr.length) {
        resolve(result);
      }
    }

  // 一次循环每一个实例
  for(var i=0; i< arr.length; i++) {
    // 基于闭包机制解决索引号不同步的问题
    (function(i){
      var item = arr[i];
      // 如果传的值不是_Promise实例,则直接存储
      if(!(item instanceof _Promise)){
       result[i] = item;
       index++;
       success();
       return;
      }
      item.then(function(res){
        result[i] = res;
        index++;
        success();
      }).catch(function(rej){
        reject(rej)
      })
    })(i)
  }
  });
}

// 支持浏览器导入和CommonJS/ES6Module模块导入
if(typeof window !== 'undefined') {
  window._Promise = _Promise;
}
if(typeof module === 'object' && typeof module.exports === 'object'){
  module.exports = _Promise;
}
})();

let p1 = new _Promise(function(resolev,reject){
 reject(300);
});

/* let p2 = p1.then(res=>{
},rej=>{
  console.log(rej);
});
p2.then(res=>{
  console.log(res); // undefined 因为p1.then(A,B)执行B函数的时候,没有任何返回值
}); */

/* let p2 = p1.then(res=>{},rej=>{
  console.log(rej);
  return _Promise.resolve('成功的实例');
  // 这里返回了一个状态为成功,值为‘成功的实例’的_Promise实例,所以p2的状态跟实例和这个返回的新实例保持一致
});
p2.then(res=>{
  console.log(res); // '成功的实例'
}); */

/* let p2 = p1.then(res=>{}, rej=>{
  console.log(rej, a); // 这里执行报错,所以p2的状态为失败
});
p2.then(res=>{
  console.log(res);
}, rej=>{
  // 所以执行的是失败的函数,值为p1.then中执行函数报错的原因
  console.log(rej);
}); */


let q = _Promise.all([10, _Promise.resolve(20), 'ss', _Promise.resolve(300), _Promise.reject(404)]);
console.log(q);
q.then(res=>{
  console.log(res);
})
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值