手写promise

首先我们分析一下promise的基本原理:

  1. Promise是一个类,在执行这个类的时候会传入一个执行器,这个执行器会立即执行。
  2. Promise会有三种状态:
    • Pending 等待
    • Fulfilled 完成
    • Rejected 失败
  3. 状态只能由Pending --> Fulfilled或者Pending --> Rejected,且一旦发生改变便不可二次修改。
  4. Promise中使用resolve和reject两个函数来更改状态。
  5. then方法内部做的事情就是状态判断
    • 如果状态是成功,调用成功回调函数
    • 如果状态是失败,调用失败回调函数
//先定义三个常量表示状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

//新建MyPromise类
class MyPromise{
	constructor(executor){
		//executor是一个执行器,进入会立即执行
		//并传入resolve和reject方法
		try{
			executor(this.resolve,this.reject)
		}catch(error){
			this.reject(error)
		}
	}
	//储存状态的变量,初始值是pending
	status = PENDING;
	//成功后的值
	value = null;
	//失败之后的原因
	reason = null;

	//存储成功回调函数
	onFulfilledCallbacks = [];
	//存储失败回调函数
	onRejectedCallbacks = [];

	//更改成功后的状态
	resolve = (value) => {
		//只有状态是等待,才执行状态修改
		if(this.status === PENDING){
			//状态修改为成功
			this.status = FULFILLED;
			//保存成功之后的值
			this.value = value;
			//resolve里面将所有成功的回调拿出来执行
			while(this.onFulfilledCallbacks.length){
				//Array.shift()取出数组第一个元素,然后()调用,shift不是纯函数,取出后,数组将失去该元素,直到数组为空
				this.onFulfilledCallbacks.shift()(value)
			}
		}
	}
	
	//更改失败后的状态
	reject = (reason) => {
		//只有状态是等待,才执行状态修改
		if(this.status === PENDING){
			//状态修改为失败
			this.status = REJECTED;
			//保存失败后的原因
			this.reason = reason;
			//resolve里面将所有失败的回调拿出来执行
			while(this.onRejectedCallbacks,length){
				this.onRejectedCallbacks.shift()(reason)
			}
		}
	}
	then(onFulfilled,onRejected){
		const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
		const realOnRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason};

		//为了链式调用这里直接创建一个MyPromise,并在后面return出去
		const promise2 = new MyPromise((resolve,reject) => {
			const fulfilledMicrotask = () => {
				//创建一个微任务等待promise2完成初始化
				queueMicrotask(() => {
					try{
						//获取成功回调函数的执行结果
						const x = realOnFulfilled(this.value);
						//传入resolvePromise集中处理
						resolvePromise(promise2,x,resolve,reject);
					}catch(error){
						reject(error)
					}
				})
			}

			const rejectedMicrotask = () => {
				//创建一个微任务等待promise2完成初始化
				queueMicrotask(() => {
					try{
						//调用失败回调,并且把原因返回
						const x = realOnRejected(this.reason);
						//传入resolvePromise集中处理
						resolvePromise(promise2,x,resolve,reject);
					}catch(error){
						reject(error)
					}
				})
			}
			//判断状态
			if(this.status === FULFILLED){
				fulfilledMicrotask()
			}else if(this.status === REJECTED){
				rejectedMicrotask()
			}else if(this.status === PENDING){
				//等待
				//因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来
				//等到执行成功失败函数的时候再传递
				this.onFulfilledCallbacks.push(fulfilledMicrotask);
				this.onRejectedCallbacks.push(rejectedMicrotask);
			}
		})
		return promise2;
	}
	//resolve静态方法
	static resolve(parameter){
		//如果传入MyPromise就直接返回
		if(parameter instanceof MyPromise){
			return parameter;
		}

		//转成常规方式
		return new MyPromise(resolve => {
			resolve(parameter);
		})
	}

	//reject静态方法
	static reject(reason){
		return new MyPromise((resolve,reject) => {
			reject(reason);
		})
	}
}

function resolvePromise(promise2,x,resolve,reject){
	//如果相等了,说明return的是自己,抛出类型错误并返回
	if(promise2 === x){
		return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
	}
	//判断x是不是MyPromise实例对象
	if(x instanceof MyPromise){
		//执行x,调用then方法,目的是将其状态变为fulfilled或者rejected
		//x.then(value => resolve(value),reason => reject(reason))
		//简化之后
		x.then(resolve,reject)
	}else{
		//普通值
		resolve(x)
	}
}

module.exports = MyPromise;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值