es6 手写Promise实现源码

实现思路:
	因为Promise是es6出来的,所以整体设计都使用es5的类和普通function
	
	基本大纲:
	(1)当new Promise时,在Promise类内部执行传入的方法体,形参resovle和reject都是类内部定义的方法,用来改变Promise内部的状态和值
	
	(2)当使用.then接收时
		会使用.then传入的方法参数,调用该方法,传入执行器中的值,
			若执行器同步执行,直接调用
			若执行器异步执行,则保存方法到.then前一个Promise上,待到上一个Promise执行器执行时再一起调用
		
	(3)当使用.then返回一个Promise对象时
		调用传入.then的方法参数,获取方法的返回值,若返回值是非Promise对象/异常,修改状态和值返回,若返回值是Promise对象,通过.then获取获取到该Promise对象执行结果,然后修改返回的Pomise的状态和值
		若获取到的Promise是同步执行,则直接修改返回的Promise的状态和值
		若获取到的Promise是异步执行,则会等到执行时,再修改返回的Promise状态和值

接下来是分步骤实现:

Promise类初始结构搭建:

let p = new Promise((resolve, reject) => {
    
     //传入的函数是在Promise内部执行的,参数也是在执行时进行传递的

  throw new Error('errr');	//遇到抛出异常的情况
  resolve('jeff');		//遇到同步执行器调用的情况
  setTimeout(() => {
    
    	
    resolve('jeff');   //异步执行器resolve调用情况
    reject('errrr');  //异步执行器reject调用情况
  },2000)
  
});

//调用方式
const res=p.then((res)=>{
    
    },(err)=>{
    
    }).then(...)
const res=p.then((res)=>{
    
    }).catch((err)=>{
    
    ...})

function Promise(executor) {
    
    
   this.PromiseState = 'pending'; //初始状态为pending
   this.PromiseResult = '';		 //初始值是空
   executor(resovle,reject);	//调用传入的方法体,传入resovle/reject形参还未定义
}

resolve、reject执行器和异常捕捉的实现:

//resolve、reject只是改变Promise内部状态和值,.then才会返回结果
//Promise内部的状态只能改变一次,再次改变不会产生影响

function Promise(executor) {
    
    
   this.PromiseState = 'pending'; //初始状态为pending
   this.PromiseResult = '';		 //初始值是空

   
   let that = this;  //普通function调用时上下文不确定,this指向会出问题
   
   function resolve(val) {
    
     //直接使用this会undefined,因为箭头函数和Promise都属于es6,所以这里不使用箭头函数
	    if (that.PromiseState !== "pending") {
    
     //使得状态只能改变一次
	      return;
	    }
	    that.PromiseState = 'fullfilled'; //设置promise对象状态
	    that.PromiseResult = val; //设置promise对象的值
   }
	
   function reject(err) {
    
      //失败回调
	    if (that.PromiseState !== "pending") {
    
    
	      return;
	    }
	    that.PromiseResult = err;
	    that.PromiseState = "rejected";
   }
 
  try {
    
     //try-catch处理throw抛出异常改变Promise状态
    	executor(resolve,reject); //执行传入的函数,传递的形参是在Promise内的方法,因为上下文不明确,this会undefined  
  } catch (err) {
    
    
    	reject(err);
  }
}

.then方法接收执行器调用传入的内容实现:

//.then整个方法是同步执行的,.then传入的方法参数,会在执行器执行后执行,故在异步情况,同步执行.then时能先进行方法参数的保存
//resovle/reject执行器只是改变状态和值,.then传入的方法和参数才是接收对应状态下的值
//.then会接收两个方法参数,分别对应resolve/reject执行后调用,方法参数未执行器调用时传入的值
/**
//若执行器是同步调用:根据执行器调用后Promise对象的状态和值,对应调用方法参数并传入值
//若执行器是异步调用:
	因为.then这些方法是同步执行的,在执行.then时,Promise对象的状态是pending,状态和值都未改变,而参数方法需要等到状态和值改变时才调用
	因此,需要在pending时将方法参数保存下来,选择通过this保存到实例上
	因为.then可以分开调用,所以需要将分开调用的各自的方法参数保存起来,选择保存进数组中
	在异步任务中等待resolve/reject执行器执行,此时Promise对象状态和值改变
	当rosolve/reject执行器执行后,遍历数组,执行对应情况下保存的.then中的方法参数,并传入执行器调用时传入的值
*/
Promise.prototype.then =function(onResolved, onRejected) {
    
    //不能使用箭头函数,箭头函数的this会指向外部函数定义时的this,即全局,普通函数的上下文会指向实例

    let that = this;
  
      //同步执行下的回调
    if (that.PromiseState === 'fullfilled') {
    
    
      onResolved(that.PromiseResult)

    }
    //同步执行下的回调
    if (that.PromiseState === 'rejected') {
    
    
      onRejected(that.PromiseResult)
    }

    if (that.PromiseState === 'pending') {
    
     
     //当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调,待到改变状态再执行,若使用循环等监听耗费性能
      
      that.callbacks.push({
    
    
        onResolved,
        onRejected
      }) 
    }
  })
}


function Promise(executor) {
    
    
   this.PromiseState = 'pending'; //初始状态为pending
   this.PromiseResult = '';		 //初始值是空
    //异步操作下的保存的回调,若有多个.then分开调用,则都会保存下来
   this.callbacks =[];
   
   
   let that = this;  //普通function调用时上下文不确定,this指向会出问题
   
   function resolve(val) {
    
     //直接使用this会undefined,因为箭头函数和Promise都属于es6,所以这里不使用箭头函数
	    if (that.PromiseState !== "pending") {
    
     //使得状态只能改变一次
	      return;
	    }
	    that.PromiseState = 'fullfilled'; //设置promise对象状态
	    that.PromiseResult = val; //设置promise对象的值
	    
	    //执行器异步执行时,同步执行跳过,因为callback并未保存方法
	    if (that.callbacks.length) {
    
     //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
	      //当异步执行器改变了状态
	      that.callbacks.forEach(function (callback) {
    
    
	        callback.onResolved(that.PromiseResult);
	      })
	    }
   }
	
   function reject(err) {
    
      //失败回调
	    if (that.PromiseState !== "pending") {
    
    
	      return;
	    }
	    that.PromiseResult = err;
	    that.PromiseState = "rejected";
	    //执行器异步执行时触发,同步执行跳过,因为callbacks并未保存方法
	    if (that.callbacks.length) {
    
     //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
	      //当异步执行器改变了状态
	      that.callbacks.forEach(function(callback){
    
    
	        callback.onRejected(that.PromiseResult);
	      })
	    }
   }
 
  try {
    
     //try-catch处理throw抛出异常改变Promise状态
    	executor(resolve,reject); //执行传入的函数,传递的形参是在Promise内的方法,因为上下文不明确,this会undefined  
  } catch (err) {
    
    
    	reject(err);
  }
}

.then返回Promise实例对象实现:

//因为当.then中传入的方法参数执行后,能够获取到返回值,且.then返回的Promise1对象的状态和值和返回值相关
//所以,.then返回Promise实例对象的实现,应该在.then中传入的方法参数执行后进行,即在上一个模块的基础上进行
//且在获取到返回值后,需要调用返回的Promise1对象的resolve/reject方法,而这两个方法在Promise外部不好获取
	//所以将.then中传入的方法参数执行实现和返回.then返回Promise对象的实现修改为:
	/**
		Promise.prototype.then =function(onResolved, onRejected) {
			return new Promise(function(resolve,reject){
				.then中传入的方法参数执行实现和返回.then返回Promise对象的实现
				...
			})
		}
    */
//当方法参数的返回值是正常值/异常时,直接调用要返回的Promise1对象的reject/resolve执行器
//当方法参数的返回值是Promise对象时,需要手动调用该Promise对象.then方法,并传入两个方法参数,在该Promise对象的执行器执行后,就能获取到传递给该Promise对象执行器的值/异常
	//在获取到方法参数返回的Promise的值/异常,即在手动调用.then的两个方法参数中,再调用返回的Promise1对象的resolve/reject方法,就能修改其状态和值,同方法参数返回的Promise状态和值相同
//因为.then中方法参数的执行,以及返回内容的获取以及根据返回内容修改.then返回的Promise状态和值是递进执行的,所以抽离成一个方法

Promise.prototype.then =function(onResolved, onRejected) {
    
    //不能使用箭头函数,箭头函数的this会指向外部函数定义时的this,即全局,普通函数的上下文会指向实例

  let that = this;

  return new Promise(function (resolve, reject) {
    
      //.then函数必定会返回一个Promise
    
    //封装根据.then返回值进行修改返回的Promise对象的状态和值的方法
    function callback(onExcuter) {
    
    
      try {
    
     //捕捉.then方法中抛出的异常
        let res=onExcuter(that.PromiseResult); //执行传递给.then的函数参数,并获取返回结果,以便.then链式调用
        if (res instanceof Promise) {
    
     //如果返回结果是Promise实例,通过.then获取到状态和值则修改返回的Promise状态和结果
          res.then((val) => {
    
    
            resolve(val); //执行后,修改.then返回的Promise对象的值和状态
          }, (err) => {
    
    
            reject(err);
          })

        } else {
    
      //返回普通值
          resolve(res); 
        }        
      } catch (err) {
    
    
        
        reject(err);
      }
    }
    
      //同步执行下的回调
    if (that.PromiseState === 'fullfilled') {
    
    
      
      callback(onResolved);

    }
    //同步执行下的回调
    if (that.PromiseState === 'rejected') {
    
    
      
      callback(onRejected);
      
    }

    if (that.PromiseState === 'pending') {
    
     
     //当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调给调用.then的Promise上,待到改变状态(调用.then的Promise执行器执行)再执行,若使用循环等监听耗费性能
      
      that.callbacks.push({
    
    
        onResolved: function () {
    
    
          callback(onResolved);

        },
        onRejected: function () {
    
    
          callback(onRejected);
        }
      }) 
    }
  })
  
}

链式.then调用实现:

因为上一个模块已经实现了每次.then返回一个Promise对象,所以已经实现了.then链式调用
p.then(方法参数1,方法参数2).then(方法参数11,方法参数22)
调用过程:
	当p的执行器resovle/reject/异常执行后,会调用第一个.then对应的方法参数,若p内为异步则会先保存,待到执行器执行后再调用
	异步情况且返回Promise对象:
	当第一个.then中的方法参数执行后,会根据返回值和异同步状态调用返回Promise的执行器方法,返回的Promise对象会做对应的修改,状态从pending改变
	第二个.then因为为同步调用,已经保存了第二个.then中的方法参数到第一个.then返回的Promise对象中,当第一个.then返回的Promise的执行器执行后,修改返回的Promise状态和值,然后才会触发保存到该Promise中的第二个.then中的方法参数,传入执行器执行内容并获取第二个.then方法参数的返回值,然后解析该返回值,修改(即调用第二个.then返回Promise的执行器)第二个.then返回的Promise的状态和值,在修改时若之后还有保存的.then的方法参数,则又会执行其方法参数,并根据返回值修改返回的Promise状态
	
	Promise内每次执行器执行(非then内):修改执行器所属的Promise的值,调用保存的之后的.then的方法参数并传入执行器获取的值,并获取方法参数的返回值,返回值又会通过.then返回的Promise对象的执行器传入调用,从而修改了.then返回的Promise的状态和值,.then返回的Promise对象中又保存了之后的.then中的方法参数,则会在修改返回的Promise时,又调用之后.then中的方法参数,获取返回值并修改之后.then返回的Promise的状态和值,之后的.then以此类推
	

.catch、异常穿透、以及不指定.then参数也不中断后续执行实现:

//.catch实现:
	//因为.catch和.then的唯一区别是.catch只接收失败回调(reject/throw),返回值等和.then无区别,故完全可以使用.then方法只传入reject对应的回调实现
//异常穿透:
	//当未传递.then第二个reject对应的方法参数时,内部手动创建一个会抛出异常的对应回调函数
	//则当.then链式调用时,若异步,异常函数会绑定到上一个Promise上,执行reject时,会调用之后.then对应的手动创建的异常函数,会被try-catch一直捕捉,从而一直返回reject形式的Promise,
	//直到遇到最后的.catch,.catch对应的回调会在上一个Promise执行reject时调用,从而能接收到链式调用中第一个调用reject/throw传入的值

//.then不传入方法参数也不影响执行
	//.then方法实现内部进行判断,若没有传入对应函数,则手动创建一个函数,返回接收到的值,则resolve执行时,调用对应的手动创建的函数,返回值会被放进.then返回的Promise中
	
Promise.prototype.catch = function (onRejected) {
    
    //添加.catch方法,返回结果是和.then相同的返回对象

  return this.then(undefined, onRejected);

}

Promise.prototype.then =function(onResolved, onRejected) {
    
    //不能使用箭头函数,箭头函数的this会指向外部函数定义时的this,即全局,普通函数的上下文会指向实例

  let that = this;

  if (typeof onRejected !== 'function') {
    
     //实现异常穿透,当未传递.then第二个参数,创建一个函数,当进入callback中会被try-catch捕捉从而修改状态未rejected,值为传入reject的值,若之后的.then没有第二个参数,会一直被捕捉,最终因为.catch中传入了onRejected函数,不为undefined,从而将抛出的值接收,实现异常传统效果,故只要指定一个会修改状态为rejected的函数即可,故该函数还可以修改为返回一个调用了reject(err)的Promise实例对象也可以
                                          //若不指定函数,则会在调用时为undefined的被try-catch捕捉,捕捉的内容也是undefined不是方法,故最终.catch捕获到的内容会是undefined 不是方法,而非reject/throw中的内容,未能实现异常穿透
    onRejected = (err) => {
    
    
      throw err;
    }
  }

  if (typeof onResolved !== 'function') {
    
     //实现若第一个参数未传递,会使用该方法,返回的Promise的值依旧为resolve的值和fullfilled状态,不会影响链式.then的执行,否则会因为undefined不是方法中断
    onResolved = (val) => val;
  }


  return new Promise(function (resolve, reject) {
    
      //.then函数必定会返回一个Promise
    
    //封装根据.then返回值进行修改返回的Promise对象的状态和值的方法
    function callback(onExcuter) {
    
    
      try {
    
     //捕捉.then方法中抛出的异常
        let res=onExcuter(that.PromiseResult); //执行传递给.then的函数参数,并获取返回结果,以便.then链式调用
        if (res instanceof Promise) {
    
     //如果返回结果是Promise实例,通过.then获取到状态和值则修改返回的Promise状态和结果
          res.then((val) => {
    
    
            resolve(val); //执行后,修改.then返回的Promise对象的值和状态
          }, (err) => {
    
    
            reject(err);
          })

        } else {
    
      //返回普通值
          resolve(res); 
        }        
      } catch (err) {
    
    
        
        reject(err);
      }
    }
    
      //同步执行下的回调
    if (that.PromiseState === 'fullfilled') {
    
    
      
      callback(onResolved);

    }
    //同步执行下的回调
    if (that.PromiseState === 'rejected') {
    
    
      
      callback(onRejected);
      
    }

    if (that.PromiseState === 'pending') {
    
      //当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调,待到改变状态再执行,若使用循环等监听耗费性能
      
      that.callbacks.push({
    
    
        onResolved: function () {
    
    
          callback(onResolved);

        },
        onRejected: function () {
    
    
          callback(onRejected);
        }
      }) 
    }
  })
  
}

修改.then的方法参数调用方式,使其一直为异步调用,进入异步队列中:

//在执行.then中方法参数时,添加setTimeout,使其为异步调用,使得和实际Promise执行效果相同
function Promise(executor) {
    
    
  //executor内部函数同步调用,resolve/rejected对应的.then等异步调用

  this.PromiseState = 'pending';
  this.PromiseResult = '';
  //异步操作下的保存的回调,若有多个.then分开调用,则都会保存下来
  this.callbacks =[];
  
  let that = this;

  function resolve(val) {
    
     //直接使用this会undefined,因为箭头函数和Promise都属于es6,所以这里不使用箭头函数
    if (that.PromiseState !== "pending") {
    
     //使得状态只能改变一次
      return;
    }
    that.PromiseState = 'fullfilled'; //设置promise对象状态
    that.PromiseResult = val; //设置promise对象的值


    //执行器异步执行时,同步执行跳过,因为callback并未保存方法
    if (that.callbacks.length) {
    
     //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
      //当异步执行器改变了状态
      setTimeout(() => {
    
    //修改调用方法为异步调用
        that.callbacks.forEach(function (callback) {
    
    
          callback.onResolved(that.PromiseResult);
        })  
      })
      
    }

  }

  function reject(err) {
    
      //失败回调
    if (that.PromiseState !== "pending") {
    
    
      return;
    }
    that.PromiseResult = err;
    that.PromiseState = "rejected";
    
    //执行器异步执行时触发,同步执行跳过,因为callbacks并未保存方法
    if (that.callbacks.length) {
    
     //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
      //当异步执行器改变了状态
      setTimeout(() => {
    
     //修改调用方法为异步调用
        that.callbacks.forEach(function(callback){
    
    
          callback.onRejected(that.PromiseResult);
        })
      })
      
    }
    
  }
  
  try {
    
     //try-catch处理throw抛出异常改变Promise状态
    executor(resolve,reject); //执行传入的函数,传递的形参是在Promise内的方法,因为上下文不明确,this会undefined  
  } catch (err) {
    
    
    reject(err);
  }
  
  
}

Promise.prototype.then =function(onResolved, onRejected) {
    
    //不能使用箭头函数,箭头函数的this会指向外部函数定义时的this,即全局,普通函数的上下文会指向实例

  let that = this;

  if (typeof onRejected !== 'function') {
    
     //实现异常穿透,当未传递.then第二个参数,创建一个函数,当进入callback中会被try-catch捕捉从而修改状态未rejected,值为传入reject的值,若之后的.then没有第二个参数,会一直被捕捉,最终因为.catch中传入了onRejected函数,不为undefined,从而将抛出的值接收,实现异常传统效果,故只要指定一个会修改状态为rejected的函数即可,故该函数还可以修改为返回一个调用了reject(err)的Promise实例对象也可以
                                          //若不指定函数,则会在调用时为undefined的被try-catch捕捉,捕捉的内容也是undefined不是方法,故最终.catch捕获到的内容会是undefined 不是方法,而非reject/throw中的内容,未能实现异常穿透
    onRejected = (err) => {
    
    
      throw err;
    }
  }

  if (typeof onResolved !== 'function') {
    
     //实现若第一个参数未传递,会使用该方法,返回的Promise的值依旧为resolve的值和fullfilled状态,不会影响链式.then的执行,否则会因为undefined不是方法中断
    onResolved = (val) => val;
  }


  return new Promise(function (resolve, reject) {
    
      //.then函数必定会返回一个Promise
    
    //封装根据.then返回值进行修改返回的Promise对象的状态和值的方法
    function callback(onExcuter) {
    
    
      try {
    
     //捕捉.then方法中抛出的异常
        let res=onExcuter(that.PromiseResult); //执行传递给.then的函数参数,并获取返回结果,以便.then链式调用
        if (res instanceof Promise) {
    
     //如果返回结果是Promise实例,通过.then获取到状态和值则修改返回的Promise状态和结果
          res.then((val) => {
    
    
            resolve(val); //执行后,修改.then返回的Promise对象的值和状态
          }, (err) => {
    
    
            reject(err);
          })

        } else {
    
      //返回普通值
          resolve(res); 
        }        
      } catch (err) {
    
    
        
        reject(err);
      }
    }
    
      //同步执行下的回调
    if (that.PromiseState === 'fullfilled') {
    
    
      setTimeout(() => {
    
    //修改调用方法为异步调用
        callback(onResolved);  
      })
      

    }
    //同步执行下的回调
    if (that.PromiseState === 'rejected') {
    
    
      setTimeout(() => {
    
    //修改调用方法为异步调用
        callback(onRejected);
      })
      
    }

    if (that.PromiseState === 'pending') {
    
      //当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调,待到改变状态再执行,若使用循环等监听耗费性能
      
      that.callbacks.push({
    
    
        onResolved: function () {
    
    
          callback(onResolved);

        },
        onRejected: function () {
    
    
          callback(onRejected);
        }
      }) 
    }
  })
  
}

Promise最终实现:

function Promise(executor) {
    
    
  //executor内部函数同步调用,resolve/rejected对应的.then等异步调用

  this.PromiseState = 'pending';
  this.PromiseResult = '';
  //异步操作下的保存的回调,若有多个.then分开调用,则都会保存下来
  this.callbacks =[];
  
  let that = this;

  function resolve(val) {
    
     //直接使用this会undefined,因为箭头函数和Promise都属于es6,所以这里不使用箭头函数
    if (that.PromiseState !== "pending") {
    
     //使得状态只能改变一次
      return;
    }
    that.PromiseState = 'fullfilled'; //设置promise对象状态
    that.PromiseResult = val; //设置promise对象的值


    //执行器异步执行时,同步执行跳过,因为callback并未保存方法
    if (that.callbacks.length) {
    
     //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
      //当异步执行器改变了状态
      setTimeout(() => {
    
    //修改调用方法为异步调用
        that.callbacks.forEach(function (callback) {
    
    
          callback.onResolved(that.PromiseResult);
        })  
      })
      
    }

  }

  function reject(err) {
    
      //失败回调
    if (that.PromiseState !== "pending") {
    
    
      return;
    }
    that.PromiseResult = err;
    that.PromiseState = "rejected";
    
    //执行器异步执行时触发,同步执行跳过,因为callbacks并未保存方法
    if (that.callbacks.length) {
    
     //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
      //当异步执行器改变了状态
      setTimeout(() => {
    
     //修改调用方法为异步调用
        that.callbacks.forEach(function(callback){
    
    
          callback.onRejected(that.PromiseResult);
        })
      })
      
    }
    
  }
  
  try {
    
     //try-catch处理throw抛出异常改变Promise状态
    executor(resolve,reject); //执行传入的函数,传递的形参是在Promise内的方法,因为上下文不明确,this会undefined  
  } catch (err) {
    
    
    reject(err);
  }
  
  
}

Promise.prototype.then =function(onResolved, onRejected) {
    
    //不能使用箭头函数,箭头函数的this会指向外部函数定义时的this,即全局,普通函数的上下文会指向实例

  let that = this;

  if (typeof onRejected !== 'function') {
    
     //实现异常穿透,当未传递.then第二个参数,创建一个函数,当进入callback中会被try-catch捕捉从而修改状态未rejected,值为传入reject的值,若之后的.then没有第二个参数,会一直被捕捉,最终因为.catch中传入了onRejected函数,不为undefined,从而将抛出的值接收,实现异常传统效果,故只要指定一个会修改状态为rejected的函数即可,故该函数还可以修改为返回一个调用了reject(err)的Promise实例对象也可以
                                          //若不指定函数,则会在调用时为undefined的被try-catch捕捉,捕捉的内容也是undefined不是方法,故最终.catch捕获到的内容会是undefined 不是方法,而非reject/throw中的内容,未能实现异常穿透
    onRejected = (err) => {
    
    
      throw err;
    }
  }

  if (typeof onResolved !== 'function') {
    
     //实现若第一个参数未传递,会使用该方法,返回的Promise的值依旧为resolve的值和fullfilled状态,不会影响链式.then的执行,否则会因为undefined不是方法中断
    onResolved = (val) => val;
  }


  return new Promise(function (resolve, reject) {
    
      //.then函数必定会返回一个Promise
    
    //封装根据.then返回值进行修改返回的Promise对象的状态和值的方法
    function callback(onExcuter) {
    
    
      try {
    
     //捕捉.then方法中抛出的异常
        let res=onExcuter(that.PromiseResult); //执行传递给.then的函数参数,并获取返回结果,以便.then链式调用
        if (res instanceof Promise) {
    
     //如果返回结果是Promise实例,通过.then获取到状态和值则修改返回的Promise状态和结果
          res.then((val) => {
    
    
            resolve(val); //执行后,修改.then返回的Promise对象的值和状态
          }, (err) => {
    
    
            reject(err);
          })

        } else {
    
      //返回普通值
          resolve(res); 
        }        
      } catch (err) {
    
    
        
        reject(err);
      }
    }
    
      //同步执行下的回调
    if (that.PromiseState === 'fullfilled') {
    
    
      setTimeout(() => {
    
    //修改调用方法为异步调用
        callback(onResolved);  
      })
      

    }
    //同步执行下的回调
    if (that.PromiseState === 'rejected') {
    
    
      setTimeout(() => {
    
    //修改调用方法为异步调用
        callback(onRejected);
      })
      
    }

    if (that.PromiseState === 'pending') {
    
      //当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调,待到改变状态再执行,若使用循环等监听耗费性能
      
      that.callbacks.push({
    
    
        onResolved: function () {
    
    
          callback(onResolved);

        },
        onRejected: function () {
    
    
          callback(onRejected);
        }
      }) 
    }
  })
  
}

//添加.catch方法,返回结果是和.then相同的返回对象
Promise.prototype.catch = function (onRejected) {
    
    

  return this.then(undefined, onRejected);

}

class版本es6最终实现:

class Promise{
    
    
  constructor(executor) {
    
    
    this.PromiseState = 'pending';
    this.PromiseResult = '';
    //异步操作下的保存的回调,若有多个.then分开调用,则都会保存下来
    this.callbacks =[];
    
    let that = this;

    function resolve(val) {
    
     //直接使用this会undefined,因为箭头函数和Promise都属于es6,所以这里不使用箭头函数
      if (that.PromiseState !== "pending") {
    
     //使得状态只能改变一次
        return;
      }
      that.PromiseState = 'fullfilled'; //设置promise对象状态
      that.PromiseResult = val; //设置promise对象的值


      //执行器异步执行时,同步执行跳过,因为callback并未保存方法
      if (that.callbacks.length) {
    
     //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
        //当异步执行器改变了状态
        setTimeout(() => {
    
    //修改调用方法为异步调用
          that.callbacks.forEach(function (callback) {
    
    
            callback.onResolved(that.PromiseResult);
          })  
        })
        
      }

    }

    function reject(err) {
    
      //失败回调
      if (that.PromiseState !== "pending") {
    
    
        return;
      }
      that.PromiseResult = err;
      that.PromiseState = "rejected";
      
      //执行器异步执行时触发,同步执行跳过,因为callbacks并未保存方法
      if (that.callbacks.length) {
    
     //说明执行器函数异步执行,即调用.then时,状态还未改变,在.then中保存了回调
        //当异步执行器改变了状态
        setTimeout(() => {
    
     //修改调用方法为异步调用
          that.callbacks.forEach(function(callback){
    
    
            callback.onRejected(that.PromiseResult);
          })
        })
        
      }
      
    }
    
    try {
    
     //try-catch处理throw抛出异常改变Promise状态
      executor(resolve,reject); //执行传入的函数,传递的形参是在Promise内的方法,因为上下文不明确,this会undefined  
    } catch (err) {
    
    
      reject(err);
    }
  }

  then(onResolved, onRejected) {
    
    
    let that = this;

    if (typeof onRejected !== 'function') {
    
     //实现异常穿透,当未传递.then第二个参数,创建一个函数,当进入callback中会被try-catch捕捉从而修改状态未rejected,值为传入reject的值,若之后的.then没有第二个参数,会一直被捕捉,最终因为.catch中传入了onRejected函数,不为undefined,从而将抛出的值接收,实现异常传统效果,故只要指定一个会修改状态为rejected的函数即可,故该函数还可以修改为返回一个调用了reject(err)的Promise实例对象也可以
                                            //若不指定函数,则会在调用时为undefined的被try-catch捕捉,捕捉的内容也是undefined不是方法,故最终.catch捕获到的内容会是undefined 不是方法,而非reject/throw中的内容,未能实现异常穿透
      onRejected = (err) => {
    
    
        throw err;
      }
    }

    if (typeof onResolved !== 'function') {
    
     //实现若第一个参数未传递,会使用该方法,返回的Promise的值依旧为resolve的值和fullfilled状态,不会影响链式.then的执行,否则会因为undefined不是方法中断
      onResolved = (val) => val;
    }


    return new Promise(function (resolve, reject) {
    
      //.then函数必定会返回一个Promise
        
      //封装根据.then返回值进行修改返回的Promise对象的状态和值的方法
      function callback(onExcuter) {
    
    
        try {
    
     //捕捉.then方法中抛出的异常
          let res=onExcuter(that.PromiseResult); //执行传递给.then的函数参数,并获取返回结果,以便.then链式调用
          if (res instanceof Promise) {
    
     //如果返回结果是Promise实例,通过.then获取到状态和值则修改返回的Promise状态和结果
            res.then((val) => {
    
    
              resolve(val); //执行后,修改.then返回的Promise对象的值和状态
            }, (err) => {
    
    
              reject(err);
            })

          } else {
    
      //返回普通值
            resolve(res); 
          }        
        } catch (err) {
    
    
          
          reject(err);
        }
      }
      
        //同步执行下的回调
      if (that.PromiseState === 'fullfilled') {
    
    
        setTimeout(() => {
    
    //修改调用方法为异步调用
          callback(onResolved);  
        })
        

      }
      //同步执行下的回调
      if (that.PromiseState === 'rejected') {
    
    
        setTimeout(() => {
    
    //修改调用方法为异步调用
          callback(onRejected);
        })
        
      }

      if (that.PromiseState === 'pending') {
    
      //当.then方法同步执行,但执行器函数未执行,状态未改变时,保存传递给.then的参数回调,待到改变状态再执行,若使用循环等监听耗费性能
        
        that.callbacks.push({
    
    
          onResolved: function () {
    
    
            callback(onResolved);

          },
          onRejected: function () {
    
    
            callback(onRejected);
          }
        }) 
      }
    })
  }

  catch(onRejected) {
    
    

    return this.then(undefined, onRejected);

  }
}

类方法实现,不能绑定到原型上,因为实例会继承原型上的属性:
Promise.resolve实现:

//若传入非Promise对象,则直接调用返回的Promise对象的resolve方法,并传入
//若传入Promise对象,则手动添加.then并创建两个方法参数绑定到传入的Promise对象上,当传入的Promise对象执行器执行后,则会调用.then中对应的方法参数,并传入执行器执行值,然后通过要返回的Promise对象的执行器进行调用
Promise.resolve = function (val) {
    
    
  return new Promise((resolve,reject) => {
    
    
    if (val instanceof Promise) {
    
    
      val.then((res) => {
    
    
        resolve(res);
       }, (err) => {
    
    
        reject(err);
      })
    } else {
    
    
      resolve(val)
    }
  })
}

Promise.reject实现:

//和Promise.resolve原理类似,不过是无论传入何值都会返回rejected状态、值为传入值的Promise对象
Promise.reject = function (val) {
    
    
  return new Promise((resolve,reject) => {
    
    
    reject(val);
  })
}

Promise.all实现:

//all方法需要等到传入的promise都resolve才会执行返回的Promise对象的resolve方法
	//通过计数器实现,每执行了一次.then中的第一个方法参数,就证明成了一次,当次数等于数组长度时满足

//all方法返回的数组内容的顺序和传入的promise的顺序是一致的
	//为了避免后方的promise先resolve,不能直接使用数组.push方法保存结果值
	//选择使用数组下标保存结果值
//只要有一个返回失败,则最终结果返回失败,故只需要调用reject就行,利用了Promise状态只能改变一次的特点
Promise.all = function (arr) {
    
    
  return new Promise((resolve, reject) => {
    
    
    let counts = 0;
    let res = [];
    for (let i = 0; i < arr.length; i++)
    {
    
    
      arr[i].then((ans) => {
    
     //方法未实现传入普通值也能.then获取,实际的Promise是能够传入普通值的
        counts++;
        res[i] = ans;
        if (counts === arr.length) {
    
    
          resolve(res);
        }
      }, (err) => {
    
    
        reject(err);
      })  
    }
  })
}

Promise.race实现:

//遍历传入的Promise对象的数组,利用Promise状态只能改变一次的特性,哪个Promise先执行执行器,返回的Promise的状态和值就和最快执行的Promise对象相同
Promise.race=function (promises){
    
    
  return new Promise((resolve, reject) => {
    
    
    promises.forEach(promise => {
    
    	//没有实现传入的是普通值的情况,实际Promise可以传入普通值,且返回的Promise的值也是最前面的普通值
      promise.then((res) => {
    
    
        resolve(res);
      }, (err) => {
    
    
        reject(err);
      })
    })
  })
}

猜你喜欢

转载自blog.csdn.net/weixin_43294560/article/details/115266562
今日推荐