自定义Promise

一,整体结构

采用es5的语法来写:

//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){
    
    
	//定义promise构造函数
	//参数是excutor函数:同步执行
	function Promise(excutor){
    
    
		
	}
	// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象
	Promise.prototype.then=function (onResolved,onRejected){
    
    
		
	}
	// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象
	Promise.prototype.catch=function (onRejected){
    
    
		
	}
	//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象
	Promise.resolve=function(value){
    
    
		
	}
	//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象
	Promise.reject=function(reason){
    
    
		
	}
	//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)
	Promise.all=function(promises){
    
    
		
	}
	//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)
	Promise.race=function(promises){
    
    
		
	}
	//向外暴露这个Promise函数,绑定为window的属性
	window.Promise=Promise
})(window)

二,构造函数Promise的实现

第一步:因为excutor是立即同步执行的,所以在promise函数内部需要调用这个excutor函数,并且参数是resolve和reject这两个回调函数。
第二步:因为参数是这两个回调函数,所以这两个回调函数就需要事先定义好。
第三步:根据平时对promise的使用,可以知道,promise必然有个状态属性(peding,resolve,reject),还有一个用于存储结果的属性,还有一个存储回调函数的数组:

//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){
    
    
	//定义promise构造函数
	//参数是excutor函数:同步执行
	function Promise(excutor){
    
    
		//因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下
		const that=this
		that.status='pending'  //给promise对象指定状态属性,初始值为pending
		that.data=undefined  //给promise对象指定一个用于存储结果数据的属性
		that.callbacks=[]   //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} }
		
		function resolve(value){
    
    
			//如果状态不是pending,直接结束
			if(that.status!=='pending'){
    
    return}
			//将状态改为resolved
			that.status='resolved'
			//保存value数据
			that.data=value
			//如果有待执行的callback函数,立即异步执行回调函数onResolved
			if(that.callbacks.length>0){
    
    
				setTimeout(()=>{
    
    //让他异步执行,所有成功的回调
					that.callbacks.forEach(callbacksObj=>{
    
    
						callbacksObj.onResolved(value)
					})
				})
			}
		}
		function reject(reason){
    
    
			//如果状态不是pending,直接结束
			if(that.status!=='pending'){
    
    return}
			//将状态改为rejected
			that.status='rejected'
			//保存reason数据
			that.data=reason
			//如果有待执行的callback函数,立即异步执行回调函数onRejected
			if(that.callbacks.length>0){
    
    
				setTimeout(()=>{
    
    //让他异步执行,所有成功的回调
					that.callbacks.forEach(callbacksObj=>{
    
    
						callbacksObj.onRejected(reason)
					})
				})
			}
		}
		//需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数
		try{
    
    
			excutor(resolve,reject)
		}catch(error){
    
      //如果执行器抛出异常,promise对象变为rejected状态
			reject(error)
		}
		
	}
	
	// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象
	Promise.prototype.then=function (onResolved,onRejected){
    
    
		//假设当前状态还是pending状态,将回调函数保存起来
		this.callbacks.push({
    
    
			onResolved,
			onRejected
		})
	}
	// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象
	Promise.prototype.catch=function (onRejected){
    
    
		
	}
	//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象
	Promise.resolve=function(value){
    
    
		
	}
	//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象
	Promise.reject=function(reason){
    
    
		
	}
	//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)
	Promise.all=function(promises){
    
    
		
	}
	//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)
	Promise.race=function(promises){
    
    
		
	}
	//向外暴露这个Promise函数,绑定为window的属性
	window.Promise=Promise
})(window)

也就是说:这部分是excutor实参,
在这里插入图片描述
而在promise构造函数内部,第一个执行的就是这个实参函数:
在这里插入图片描述
而这里面调用了resolve(1),这个1类比于异步操作的结果
于是就去执行resolve函数,也就是说resolve是定义者定义在promise中,使用者在外面异步操作完成后调用。
而resolve里还要调用.then中的函数:
在这里插入图片描述
简单写:
在这里插入图片描述
在这里插入图片描述
这样就是先指定两个回调函数,等resolve调用时,就可以直接在callbacks里面找到并使用了。

三,then方法的实现

//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){
    
    
	const PENDING='pending'
	const RESOLVED='resolved'
	const REJECTED='rejected'
	//定义promise构造函数
	//参数是excutor函数:同步执行
	function Promise(excutor){
    
    
		//因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下
		const that=this
		that.status=PENDING  //给promise对象指定状态属性,初始值为pending
		that.data=undefined  //给promise对象指定一个用于存储结果数据的属性
		that.callbacks=[]   //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} }
		
		function resolve(value){
    
    
			//如果状态不是pending,直接结束
			if(that.status!==PENDING){
    
    return}
			//将状态改为resolved
			that.status=RESOLVED
			//保存value数据
			that.data=value
			//如果有待执行的callback函数,立即异步执行回调函数onResolved
			if(that.callbacks.length>0){
    
    
				setTimeout(()=>{
    
    //让他异步执行,所有成功的回调
					that.callbacks.forEach(callbacksObj=>{
    
    
						callbacksObj.onResolved(value)
					})
				})
			}
		}
		function reject(reason){
    
    
			//如果状态不是pending,直接结束
			if(that.status!==PENDING){
    
    return}
			//将状态改为rejected
			that.status=REJECTED
			//保存reason数据
			that.data=reason
			//如果有待执行的callback函数,立即异步执行回调函数onRejected
			if(that.callbacks.length>0){
    
    
				setTimeout(()=>{
    
    //让他异步执行,所有成功的回调
					that.callbacks.forEach(callbacksObj=>{
    
    
						callbacksObj.onRejected(reason)
					})
				})
			}
		}
		//需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数
		try{
    
    
			excutor(resolve,reject)
		}catch(error){
    
      //如果执行器抛出异常,promise对象变为rejected状态
			reject(error)
		}
		
	}
	
	// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象
	Promise.prototype.then=function (onResolved,onRejected){
    
    
		//默认的成功回调函数
		onResolved=typeof onResolved === 'function' ? onResolved : value=>value
		//指定默认的失败的回调(实现错误/异常传透的关键点)
		onRejected=typeof onRejected === 'function' ? onRejected : reason=>{
    
    throw reason}
		const that=this
		//返回一个新的promise对象,里面的参数依旧是excutor函数
		return new Promise((resolve,reject)=>{
    
    
			//调用指定的回调函数来处理那三种返回值的情况
			// 1,如果抛出异常,新promise变为rejected状态,reason为抛出的异常
			// 2,如果返回的是非promise的任意值,新promise变为resolved,value为返回的值。
			// 3,如果返回的是另一个新的promise,此promise的结果就会变成新promise的结果
			function handle(callback){
    
    
				try{
    
    
					const result =callback(that.data)
					if(result instanceof Promise){
    
      //判断返回是promise的实例对象
						result.then(
							value=>resolve(value), //当result成功时,让return的promise也成功
							reason=>reject(reason)  //当result失败时,让return的promise也失败
						)
					}else{
    
       //返回是非promise的任意值,新promise变为resolved,value为返回的值。
						resolve(result)
					}
				}catch(error){
    
       //这里写得是then的回调函数里面,抛出异常了,新promise变为rejected状态,reason为抛出的异常
					reject(error)
				}
			}
			
			if(that.status===PENDING){
    
    
				//假设当前状态还是pending状态,此时是先指定回调函数,后改变状态。将回调函数保存起来
				//因为需要改状态,所以这样写,而不是直接handle(onResolved)
				this.callbacks.push({
    
    
					onResolved(value){
    
    
						handle(onResolved)
					},
					onRejected(reason){
    
    
						handle(onRejected)
					}
				})
			}else if(that.status===RESOLVED){
    
    
				//现在已经成功了,必然已经执行了resolve函数,所以结果必然存储在this.status里面
				setTimeout(()=>{
    
    
					handle(onResolved)
				})
			}else{
    
    
				//现在已经失败,必然已经执行了reject函数,所以结果必然存储在this.status里面
				setTimeout(()=>{
    
    
					handle(onRejected)
				})
			}
		})
	}
	// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象
	Promise.prototype.catch=function (onRejected){
    
    
		return this.then(undefined,onRejected)
	}
	//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象
	Promise.resolve=function(value){
    
    
		
	}
	//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象
	Promise.reject=function(reason){
    
    
		
	}
	//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)
	Promise.all=function(promises){
    
    
		
	}
	//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)
	Promise.race=function(promises){
    
    
		
	}
	//向外暴露这个Promise函数,绑定为window的属性
	window.Promise=Promise
})(window)

四,Promise.resolve和reject的实现

//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象
	Promise.resolve=function(value){
    
    
		//返回一个promise成功/失败
		return new Promise((resolve,reject)=>{
    
    
			//value是一个promise时
			if(value instanceof Promise){
    
    //根据value的结果作为pormise的结果
				value.then(
					value=>resolve(value), //当result成功时,让return的promise也成功
					reason=>reject(reason)  //当result失败时,让return的promise也失败
				)
			}else{
    
     //value不是一个promise=>promise变为成功,数据是value
				resolve(value)
			}
		})
	}
	//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象
	Promise.reject=function(reason){
    
    
		//返回一个失败的promise
		return new Promise((resolve,reject)=>{
    
    
			reject(reason)
		})
	}

五,Promise.all方法

//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)
	Promise.all=function(promises){
    
    
		const values =new Array(promises.length)
		let acount=0
		return new Promise((resolve,reject)=>{
    
    
			//遍历获取每一个promises内部的promise
			promises.forEach((p,index)=>{
    
    
				p.then(
					value=>{
    
    
						//p成功,将成功的value保存到values里,且要按顺序
						values[index]=value
						//如果全部成功了,就将return的promise改变为成功
						acount++
						if(acount===promises.length){
    
    
							resolve(values)
						}
					},
					reason=>{
    
      //只要一个失败了,return的promise函数就失败
						reject(reason)
					}
				)
			})
		})
	}

六,Promise.race方法

//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)
	Promise.race=function(promises){
    
    
		return new Promise((resolve,reject)=>{
    
    
			//遍历获取每一个promises内部的promise
			promises.forEach((p,index)=>{
    
    
				p.then(
					value=>{
    
    //一旦有成功的,把return变为成功promise
						resolve(value)
					},
					reason=>{
    
      //一旦有失败的,把return变为失败promise
						reject(reason)
					}
				)
			})
		})

七,整体的promise

//es5里面自定义模块,用的是IIFE(函数自调用)
(function(window){
    
    
	const PENDING='pending'
	const RESOLVED='resolved'
	const REJECTED='rejected'
	//定义promise构造函数
	//参数是excutor函数:同步执行
	function Promise(excutor){
    
    
		//因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下
		const that=this
		that.status=PENDING  //给promise对象指定状态属性,初始值为pending
		that.data=undefined  //给promise对象指定一个用于存储结果数据的属性
		that.callbacks=[]   //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} }
		
		function resolve(value){
    
    
			//如果状态不是pending,直接结束
			if(that.status!==PENDING){
    
    return}
			//将状态改为resolved
			that.status=RESOLVED
			//保存value数据
			that.data=value
			//如果有待执行的callback函数,立即异步执行回调函数onResolved
			if(that.callbacks.length>0){
    
    
				setTimeout(()=>{
    
    //让他异步执行,所有成功的回调
					that.callbacks.forEach(callbacksObj=>{
    
    
						callbacksObj.onResolved(value)
					})
				})
			}
		}
		function reject(reason){
    
    
			//如果状态不是pending,直接结束
			if(that.status!==PENDING){
    
    return}
			//将状态改为rejected
			that.status=REJECTED
			//保存reason数据
			that.data=reason
			//如果有待执行的callback函数,立即异步执行回调函数onRejected
			if(that.callbacks.length>0){
    
    
				setTimeout(()=>{
    
    //让他异步执行,所有成功的回调
					that.callbacks.forEach(callbacksObj=>{
    
    
						callbacksObj.onRejected(reason)
					})
				})
			}
		}
		//需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数
		try{
    
    
			excutor(resolve,reject)
		}catch(error){
    
      //如果执行器抛出异常,promise对象变为rejected状态
			reject(error)
		}
		
	}
	
	// Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象
	Promise.prototype.then=function (onResolved,onRejected){
    
    
		//默认的成功回调函数
		onResolved=typeof onResolved === 'function' ? onResolved : value=>value
		//指定默认的失败的回调(实现错误/异常传透的关键点)
		onRejected=typeof onRejected === 'function' ? onRejected : reason=>{
    
    throw reason}
		const that=this
		//返回一个新的promise对象,里面的参数依旧是excutor函数
		return new Promise((resolve,reject)=>{
    
    
			//调用指定的回调函数来处理那三种返回值的情况
			// 1,如果抛出异常,新promise变为rejected状态,reason为抛出的异常
			// 2,如果返回的是非promise的任意值,新promise变为resolved,value为返回的值。
			// 3,如果返回的是另一个新的promise,此promise的结果就会变成新promise的结果
			function handle(callback){
    
    
				try{
    
    
					const result =callback(that.data)
					if(result instanceof Promise){
    
      //判断返回是promise的实例对象
						result.then(
							value=>resolve(value), //当result成功时,让return的promise也成功
							reason=>reject(reason)  //当result失败时,让return的promise也失败
						)
					}else{
    
       //返回是非promise的任意值,新promise变为resolved,value为返回的值。
						resolve(result)
					}
				}catch(error){
    
       //这里写得是then的回调函数里面,抛出异常了,新promise变为rejected状态,reason为抛出的异常
					reject(error)
				}
			}
			
			if(that.status===PENDING){
    
    
				//假设当前状态还是pending状态,此时是先指定回调函数,后改变状态。将回调函数保存起来
				//因为需要改状态,所以这样写,而不是直接handle(onResolved)
				this.callbacks.push({
    
    
					onResolved(value){
    
    
						handle(onResolved)
					},
					onRejected(reason){
    
    
						handle(onRejected)
					}
				})
			}else if(that.status===RESOLVED){
    
    
				//现在已经成功了,必然已经执行了resolve函数,所以结果必然存储在this.status里面
				setTimeout(()=>{
    
    
					handle(onResolved)
				})
			}else{
    
    
				//现在已经失败,必然已经执行了reject函数,所以结果必然存储在this.status里面
				setTimeout(()=>{
    
    
					handle(onRejected)
				})
			}
		})
	}
	// Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象
	Promise.prototype.catch=function (onRejected){
    
    
		return this.then(undefined,onRejected)
	}
	//Promise函数对象的方法:resolve,返回一个成功值为value的promise对象
	Promise.resolve=function(value){
    
    
		//返回一个promise成功/失败
		return new Promise((resolve,reject)=>{
    
    
			//value是一个promise时
			if(value instanceof Promise){
    
    //根据value的结果作为pormise的结果
				value.then(
					value=>resolve(value), //当result成功时,让return的promise也成功
					reason=>reject(reason)  //当result失败时,让return的promise也失败
				)
			}else{
    
     //value不是一个promise=>promise变为成功,数据是value
				resolve(value)
			}
		})
	}
	//Promise函数对象的方法:reject,返回一个失败值为reason的promise对象
	Promise.reject=function(reason){
    
    
		//返回一个失败的promise
		return new Promise((resolve,reject)=>{
    
    
			reject(reason)
		})
	}
	//Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时)
	Promise.all=function(promises){
    
    
		const values =new Array(promises.length)
		let acount=0
		return new Promise((resolve,reject)=>{
    
    
			//遍历获取每一个promises内部的promise
			promises.forEach((p,index)=>{
    
    
				p.then(
					value=>{
    
    
						//p成功,将成功的value保存到values里,且要按顺序
						values[index]=value
						//如果全部成功了,就将return的promise改变为成功
						acount++
						if(acount===promises.length){
    
    
							resolve(values)
						}
					},
					reason=>{
    
      //只要一个失败了,return的promise函数就失败
						reject(reason)
					}
				)
			})
		})
	}
	//Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的)
	Promise.race=function(promises){
    
    
		return new Promise((resolve,reject)=>{
    
    
			//遍历获取每一个promises内部的promise
			promises.forEach((p,index)=>{
    
    
				p.then(
					value=>{
    
    //一旦有成功的,把return变为成功promise
						resolve(value)
					},
					reason=>{
    
      //一旦有失败的,把return变为失败promise
						reject(reason)
					}
				)
			})
		})
	}
	//向外暴露这个Promise函数,绑定为window的属性
	window.Promise=Promise
})(window)

猜你喜欢

转载自blog.csdn.net/weixin_42349568/article/details/108932084