手写Promise源码

说到Promise,肯定首先想起它的作用—— 异步编程解决方案。出于更为深刻理解它的原因,我尝试手写了一下它的一部分功能的源码。
首先,讲一下promise的两个核心方法resolvereject,它的作用是改变promise对象的状态(resolve:pending --> fulfilled,reject:pending --> rejected),也就是说promise仅有一次更改状态的可能。

  • resolve&reject方法源码
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  constructor(executor){
    executor(this.resolve,this.reject)//执行器立即执行 --》这个执行器指的是调用promise的回调函数
  }
  status = PENDING
  resolve = () => {
    if(this.status !== PENDING) return
    this.status = FULFILLED//更改状态为成功
  }
  reject = () => {
    if(this.status !== PENDING) return
    this.status = REJECTED//更改状态为失败
  }
}

其次,关于then方法,其实就是一个根据状态执行不同回调函数的方法。但是状态的确定,并不一定是同步的,比如可能是根据请求某个后台接口的数据而确定调用resolve或者reject方法,此时,我们就需要兼容异步情况。

  • then方法源码
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject); //执行器立即执行 --》这个执行器指的是调用promise的回调函数
  }
  status = PENDING;
  value = undefined;
  reason = undefined;
  successCallBack = [];
  failCallBack = [];
  resolve = (value) => {
    if (this.status !== PENDING) return;
    this.status = FULFILLED; //更改状态为成功
    this.value = value; //保存成功之后的值
    while (this.successCallBack.length) this.successCallBack.shift()(this.value); //存在成功回调则调用
  };
  reject = (reason) => {
    if (this.status !== PENDING) return;
    this.status = REJECTED; //更改状态为失败
    this.reason = reason; //保存失败之后的值
    while (this.failCallBack.length) this.failCallBack.shift()(this.reason);//存在失败回调则调用
  };
  then(successCallBack, failCallBack) {
    if (this.status === FULFILLED) {
      successCallBack(this.value);
    } else if (this.status === REJECTED) {
      failCallBack(this.reason);
    } else {
      //异步情况 暂时储存 需要时再调用
      this.successCallBack.push(successCallBack);
      this.failCallBack.push(failCallBack);
    }
  }
}

module.exports = MyPromise;


promise还有一个显著特征,then方法的链式调用。原因是因为每次then方法执行完,都会返回一个人新的promise对象,所以它能继续调用下去。

  • then方法的链式调用源码
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject); //执行器立即执行 --》这个执行器指的是调用promise的回调函数
  }
  status = PENDING;
  value = undefined;
  reason = undefined;
  successCallBack = [];
  failCallBack = [];
  resolve = (value) => {
    if (this.status !== PENDING) return;
    this.status = FULFILLED; //更改状态为成功
    this.value = value; //保存成功之后的值
    while (this.successCallBack.length)
      this.successCallBack.shift()(this.value); //存在成功回调则调用
  };
  reject = (reason) => {
    if (this.status !== PENDING) return;
    this.status = REJECTED; //更改状态为失败
    this.reason = reason; //保存失败之后的值
    while (this.failCallBack.length) this.failCallBack.shift()(this.reason); //存在失败回调则调用
  };
  then(successCallBack, failCallBack) {
    let newPromise = new MyPromise((resolve, reject) => {
      if (this.status === FULFILLED) {
        let x = successCallBack(this.value);
        // resolve(x);
        resolvePromise(x, resolve, reject);
      } else if (this.status === REJECTED) {
        failCallBack(this.reason);
      } else {
        //异步情况 暂时储存 需要时再调用
        this.successCallBack.push(successCallBack);
        this.failCallBack.push(failCallBack);
      }
    });
    return newPromise;
  }
}
function resolvePromise(x, resolve, reject) {
  if (x instanceof MyPromise) {
    //promise 对象
    x.then(resolve, reject);
  } else {
    //普通值
    resolve(x);
  }
}
module.exports = MyPromise;

  • 基础使用
const myPromise = require("./myPromise.js");
const p = new myPromise((resolve, reject) => {
  resolve("success");
  // reject("fail");
});
p.then(value => {
    console.log(value);
    return 10
  },reason => console.log(reason)
).then(value => console.log(value))

下面附上部分其他功能(all\resolve\catch)源码

//1 接收一个执行器,并立即执行
//2 resolve、reject改变状态
//3 状态一旦改变不可更改
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
	constructor(executor){//1
		try {//捕获错误
			executor(this.resolve,this.reject)
		} catch (error) {
			this.reject(error)
		}
	}
	status = PENDING//初始化promise状态
	value = undefined//成功回调的值
	reason = undefined//失败回调的原因
	// successCallBack  = undefined // 成功回调 用于异步情况暂存回调函数
	// failCallBack  = undefined // 失败回调 用于异步情况暂存回调函数
	successCallBack = []//兼容then函数里面有多个异步回调
	failCallBack = []//兼容then函数里面有多个异步回调
	
	resolve = value =>{//2
		if(this.status !== PENDING)return//3
		this.status = FULFILLED
		this.value = value
		//异步回调执行
		// this.successCallBack&&this.successCallBack(this.value)
		while(this.successCallBack.length){//兼容then函数里面有多个异步回调 每执行完一个回调则删除当前函数项
			// this.successCallBack.shift()(this.value)
			this.successCallBack.shift()()//then里已经执行完回调并把结果包在函数中 等异步执行接受取出结果即可
		}
	}
	reject = reason =>{//2
		if(this.status !== PENDING)return//3
		this.status = REJECTED
		this.reason = reason
		//异步回调执行
		// this.failCallBack&&this.failCallBack(this.reason)
		while(this.failCallBack.length){//兼容then函数里面有多个异步回调 每执行完一个回调则删除当前函数项
			// this.failCallBack.shift()(this.reason)
			this.failCallBack.shift()()//then里已经执行完回调并把结果包在函数中 等异步执行接受取出结果即可
		}
	}
	then = (successCallBack,failCallBack) =>{
		successCallBack= successCallBack || (value => value)//兼容then可选传参情况
		failCallBack= failCallBack || (reason => {throw reason})//兼容then可选传参情况
		let promise2 = new MyPromise((resolve,reject)=>{
			if(this.status === FULFILLED){
				try {
					setTimeout(()=>{
						let x = successCallBack(this.value) //成功回调 x为返回值 链式调用中上一个then方法会返回一个值给下一个then方法
						// resolve(x)
						//判断x的值是普通值还是promise对象
						//如果是普通值 直接调用resolve
						//如果是promise对象 查看promise对象返回的结果
						//再根据promise对象返回的结果 决定调用resolve 还是 reject
						resolvePromise(promise2,x,resolve,reject)
					},0)
				} catch (error) {
					reject(error)
				}
				
			}else if(this.status === REJECTED){
				try {
					setTimeout(()=>{
						let x = failCallBack(this.reason)//失败回调 
						resolvePromise(promise2,x,resolve,reject)
					},0)
				} catch (error) {
					reject(error)
				}
					// failCallBack(this.reason)//失败回调
			}else{
				//异步情况 存着异步执行代码时 this.status为PENDING
				// this.successCallBack = successCallBack
				// this.failCallBack = failCallBack

				// this.successCallBack.push(successCallBack) 
				// this.failCallBack.push(failCallBack) 
				this.successCallBack.push(()=>{
					try {
						setTimeout(()=>{
							let x = successCallBack(this.value)
							resolvePromise(promise2,x,resolve,reject)
						},0)
					} catch (error) {
						reject(error)
					}
				})
				this.failCallBack.push(()=>{
					try {
						setTimeout(()=>{
							let x = failCallBack(this.reason)
							resolvePromise(promise2,x,resolve,reject)
						},0)
					} catch (error) {
						reject(error)
					}
				})
			
			}
		})//兼容promise的链式调用-》每个then必须返回一个promise对象,后面的调用链才能调用then方法
		return promise2
	}
	finally = (callback) =>{
		return this.then(value =>{
			// callback()
			// return value
			//为了兼容finally中异步代码
			return MyPromise.resolve(callback()).then(()=>value)
		},reason =>{
			// callback()
			// throw reason
			return MyPromise.resolve(callback()).then(()=>{throw reason})
		})
	}
	catch = (failCallBack) =>{
		return this.then(undefined,failCallBack)
	}
	static all(array) {
		let result = []
		let index = 0
		return new MyPromise((resolve,reject) =>{
			function addData(key,value){
				result[key]=value
				index++
				if(index === array.length){//异步情况下,保证所有异步代码执行完毕再抛出result
					resolve(result)
				}
			}
			for(let i = 0; i<array.length;i++){
				if(array[i] instanceof MyPromise){
					//promise对象
					let current = array[i]
					current.then(value =>addData(i,value),reason => reject(reason))
				}else{
					//普通值
					addData(i,array[i])
				}
			}
		})
		
	}
	static resolve(value){
		if(value instanceof MyPromise) return value //如果是promise对象 直接返回供promise调用链执行
		return new MyPromise(resolve => resolve(value))//如果是普通值 需要包一层promise对象
	}
		
}

function resolvePromise (promise2,x,resolve,reject){
	if(x === promise2){
		return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
	}
	if(x instanceof MyPromise){
		//promise对象
		// x.then(value =>{resolve(value)},reason =>{reject(reason)})
		x.then(resolve,reject)
	}else{
		//普通值
		resolve(x)
	}
}

module.exports = MyPromise
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值