手写Promise⭐(race,finally方法除外)

只有代码警告⚠

class MyPromise{
	constructor(executor){
		// 每一个实例都有一个状态和结果属性
		this.status = 'pending';
		this.value = undefined;
		// 创建数组存放then中的方法
		this.resolveArr = [];
		this.rejectArr = [];

		// 定义change方法修改状态
		let change = (status,value) => {
			if(this.status !== 'pending') return;   // 只要状态不是pending就不能再改了
			this.status = status;
			this.value = value;
			// 改变状态是为了执行then中的方法
			// 根据状态确定执行成功 / 失败方法
			let fnArr = status === 'resolve'? this.resolveArr:this.rejectArr;
			fnArr.forEach(item => {
				if(typeof item !== 'function') return;
				item(this.value);
			})
		}
		
		// 定义resolve和reject方法用来改变Promise实例的状态和结果
		// 为了保证执行的时候,已经基于then方法存好了需要执行的函数,需要加个判断:
		// 有方法就执行,没方法就延迟一段,等存好了再执行
		let resolve = result => {
			if(this.resolveArr.length > 0){   // 数组里有方法
				change('resolved',result);
				return;
			}
			let delayTimer = setTimeout(() => {   // 如果暂时没方法,就把它搞成异步的,只要是异步就晚于.then执行
				change('resolved',result);
				clearTimeout(delayTimer);
			},0);
		};
		let reject = reason => {
			if(this.rejectArr.length > 0){
				change('rejected',reason);
				return;
			}
			let delayTimer = setTimeout(() => {   // 如果暂时没方法,就把它搞成异步的,只要是异步就晚于.then执行
				change('rejected',reason);
				clearTimeout(delayTimer);
			},0);
		}
		
		// 每次new Promise都会立即执行executor函数,executor报错也会改为失败态
		try{
      		executor(resolve,reject);
  		}catch(err){
      		reject(err.message);
    	}
	}
	
	then(resolveFn,rejectFn){    // 原型上的then方法,then链实现
		// 如果传递的参数不是函数,比如null或者不传,要顺延到下一个then
	    // 第一个参数是null或者不传,我强行给你加一个函数,你传给我啥我就返回啥
	    if(typeof resolveFn !== 'function'){
	      resolveFn = result => {
	        return result;
	      }
	    }
	    // 第二个参数是null或者不传
	    if(typeof rejectFn !== 'function'){
	      rejectFn = reason => {
	        // return reason; 这样不行,因为前一个失败状态传到下一个就是成功态,又没报错
	        return MyPromise.reject(reason);  // 自己添加一个静态方法
	      }
	    }
	    
		return new MyPromise((resolve,reject) => {
      // 只要执行新实例的resolve/reject,就能知道新实例成功还是失败,从而决定下一个then执行哪个方法
	      this.resolveArr.push(result => {   // 先拿匿名函数包起来,类似于bind,先执行匿名函数,可以拿到执行返回结果
	        try {
	          // 不报错,接收返回结果,根据结果判断成功还是失败
	          let x = resolveFn(resolve);
	          if(x instanceof MyPromise){   // 返回一个新的实例,要看这个实例成功还是失败
	            x.then(resolve,reject);
	            return;
	          }
	          resolve(x);   // 比如返回resolve(100)这种情况
	        }catch(err){
	          // 方法执行报错,也代表新实例失败
	          reject(err.message);
	        }
	      });
	      this.rejectArr.push(reason => {
	        try {
	          // 不报错,接收返回结果,根据结果判断成功还是失败
	          let x = rejectFn(reason);
	          if(x instanceof MyPromise){   // 返回一个新的实例,要看这个实例成功还是失败
	            x.then(resolve,reject);
	            return;
	          }
	          resolve(x);   // 比如返回resolve(100)这种情况
	        }catch(err){
	          // 方法执行报错,也代表新实例失败
	          reject(err.message);
	        }
	      });
	    })
	}
	catch(rejectFn){
      return this.then(null, rejectFn);
    }


	//  静态方法
  	static resolve(result){
  	  return new MyPromise(resolve => {
      	resolve(result);
      })
  	}
  	static reject(reason){
      return new MyPromise(reason => {
      	reject(reason);
      })
  	}
  	static all(arr){
	  return new MyPromise((resolve,reject) => {
	    let index = 0,
	      results = [];
	    for(let i = 0; i < arr.length; i++){
	      let item = arr[i];
	      if(!item(item instanceof MyPromise)) continue;
	      item.then(result => {
	        index++;
	        results[i] = result;
	        if(index === arr.length){
	          resolve(result);
	        }
	      }).catch(reason => {
	        reject(reason);
	      })
	    }
    })
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值