promise 的实现原理

promise 的实现原理
class Pro {
	constructor(a) {
		this.code = "padding"
		this.value = null
		this.error = null
		let res = (value) => {

			if (this.code == "padding") {
				setTimeout(() => { //宏函数 让他再最后执行
					console.log("res被调用", this.code)
					this.value = value
					this.code = "fulfilled"
					this.onfulfilled(this.value)
				}, 0)
			}

		}
		let err = (error) => {

			if (this.code == "padding") {
				setTimeout(() => {
					console.log("err被调用", this.code)
					this.error = error
					this.code = "fulfilled"
				}, 0)
			}
		}
		a(res, err)
	}
	onthen(onfulfilled, onrejected) {
		this.onfulfilled = onfulfilled
		this.onrejected = onrejected

	}
}
let m = new Pro((a, b) => {
	a([1,2,3,4])
})
m.onthen(val=>{console.log(val,"...")},error=>{
	console.log(error)
})

但是规范制作不希望使用宏任务,应该使用微任务 queueMicrotask

class Pro {
	constructor(a) {
		this.code = "padding"
		this.value = null
		this.error = null
		let res = (value) => {

			if (this.code == "padding") {
				this.code = "fulfilled"
				queueMicrotask(() => {
					console.log("res被调用", this.code)
					this.value = value
					this.onfulfilled(this.value)
				})
			}

		}
		let err = (error) => {

			if (this.code == "padding") {
				this.code = "fulfilled"
				queueMicrotask(() => {
					console.log("err被调用", this.code)
					this.error = error
					this.onrejected(this.error)
				})
			}
		}
		a(res, err)
	}
	onthen(onfulfilled, onrejected) {
		this.onfulfilled = onfulfilled
		this.onrejected = onrejected

	}
}
let m = new Pro((a, b) => {
	setTimeout(()=>{
		a([1,2,3,4])
	},1000)
	
})
m.onthen(val=>{console.log(val,"...")},error=>{
	console.log(error)
})


优化1 支持then的多次调用

class Pro {
	constructor(a) {
		this.code = "padding"
		this.value = null
		this.error = null
		this.oklist=[]
		this.errlist=[]
		let res = (value) => {
			if (this.code == "padding") {
				queueMicrotask(() => {
					this.code = "fulfilled"
					console.log("res被调用", this.code)
					this.value = value
					this.oklist.forEach(val=>{
						val(this.value)  //微任务执行的then
					})
				})
			}
		}
		let err = (error) => {
			if (this.code == "padding") {
				queueMicrotask(() => {
					this.code = "fulfilled"
					console.log("err被调用", this.code)
					this.error = error
					this.errlist.forEach(val=>{
						val(this.value)
					})
				})
			}
		}
		a(res, err)
	}
	onthen(onfulfilled, onrejected) {
		this.oklist.push(onfulfilled)
		if(this.code=="fulfilled"){ //支持settimeout的异步调用then的操作
			onfulfilled(this.value)
		}
		this.errlist.push(onrejected)
		if(this.code=="fulfilled"){ //支持settimeout的异步调用then的操作
			onrejected(this.value)
		}
	}
}

let m = new Pro((a, b) => {
	
		a([1,2,3,4])
	
		
	
	
})
m.onthen(val=>{console.log(val,"...")},error=>{
	console.log(error)
})
m.onthen(val=>{console.log(val,".11..")},error=>{
	console.log(error)
})
setTimeout(()=>{
	m.onthen(val=>console.log(val,"22"),error=>{
	console.log(error)
})
	console.log(1)
},1000)

问题:失败和成功会同时执行 优化then的链式结构

class PromiseA {
	constructor(x) {
		this.code = "dengdai"
		this.val = null
		this.err = null
		this.valf = []
		this.errf = []
		let a = (val) => {
			queueMicrotask(
				() => {
					this.code = "going"
					this.val = val
					this.valf.forEach(val => val())
				})
		}
		let b = (err) => {
			queueMicrotask(
				() => {
					this.code = "going"
					this.err = err
					this.errf.forEach(err => err())
				})
		}
		try {
			x(a, b)
		} catch (e) {
			//TODO handle the exception
			b(e)
		}

	}
	then(val, err) {
		return new PromiseA((a, b) => {
				if (this.code == "dengdai") {

					this.valf.push(() => {
						try {
							let vals = val(this.val)
							a(vals)
						} catch (e) {
							//TODO handle the exception
							err(e)
						}
					})

					this.errf.push(() => {
						try {
							a(err(this.err))
						} catch (e) {
							err(e)
						}
					})
				
			} else if (this.code == "going") {
				if (this.val != null) {
					try {
						let e = this.val
						a(val(e))
					} catch (e) {
						//TODO handle the exception
						err(e)
					}

				} else {
					try {
						let e = this.err
						a(err(e))
					} catch (e) {
						//TODO handle the exception
						err(e)
					}

				}

			}


		})
}
}
catch
class PromiseA {
	constructor(x) {
		this.code = "dengdai"
		this.val = null
		this.err = null
		this.valf = []
		this.errf = []
		let a = (val) => {
			queueMicrotask(
				() => {
					this.code = "going"
					this.val = val
					this.valf.forEach(val => val())
				})
		}
		let b = (err) => {
			queueMicrotask(
				() => {
					this.code = "going"
					this.err = err
					this.errf.forEach(err => err())
				})
		}
		try {
			x(a, b)
		} catch (e) {
			//TODO handle the exception
			b(e)
		}

	}
	then(val, err) {
		err=err||(err=>{throw err})
		return new PromiseA((a, b) => {
				if (this.code == "dengdai") {
					if(val!=null){
						this.valf.push(() => {
							try {
								let vals = val(this.val)
								a(vals)
							} catch (e) {
								//TODO handle the exception
								b(e)
							}
						})
					}
					if(err!=null){
						this.errf.push(() => {
							try {
								let k = this.err								
								a(err(k))	
							} catch (e) {
								b(e)
							}
						})
					}
			} else if (this.code == "going") {
				if (this.val != null) {
					try {
						let e = this.val
						a(val(e))
					} catch (e) {
						//TODO handle the exception
						b(e)
					}

				} else {
					try {
						let e = this.err
						a(err(e))
					} catch (e) {
						//TODO handle the exception
						b(e)
					}

				}

			}


		})
}
catch(b){
	this.then(undefined,b)
}
}
//添加finally方法

class PromiseA {
	constructor(x) {
		this.code = "dengdai"
		this.val = null
		this.err = null
		this.valf = []
		this.errf = []
		let a = (val) => {
			queueMicrotask(
				() => {
					this.code = "going"
					this.val = val
					this.valf.forEach(val => val())
				})
		}
		let b = (err) => {
			queueMicrotask(
				() => {
					this.code = "going"
					this.err = err
					this.errf.forEach(err => err())
				})
		}
		try {
			x(a, b)
		} catch (e) {
			//TODO handle the exception
			b(e)
		}

	}
	then(val, err) {
		err=err||(err=>{throw err}) //让其为undefined时拿到值
		val=val||(val=>val)//让其为undefined时拿到值
		return new PromiseA((a, b) => {
				if (this.code == "dengdai") {
					if(val!=null){
						this.valf.push(() => {
							try {
								let vals = val(this.val)
								a(vals)
							} catch (e) {
								//TODO handle the exception
								b(e)
							}
						})
					}
					if(err!=null){
						this.errf.push(() => {
							try {
								let k = this.err								
								a(err(k))	
							} catch (e) {
								b(e)
							}
						})
					}
			} else if (this.code == "going") {
				if (this.val != null) {
					try {
						let e = this.val
						a(val(e))
					} catch (e) {
						//TODO handle the exception
						b(e)
					}

				} else {
					try {
						let e = this.err
						a(err(e))
					} catch (e) {
						//TODO handle the exception
						b(e)
					}

				}

			}


		})
}
catch(b){
	return this.then(undefined,b)
}
finally(or){
	return this.then(()=>{
		or()
	},()=>{
		or()
	})
}
}
let m = new PromiseA((res, err) => {
	res(1123)
})
m.then(val=>val+"123").then(val=>{console.log(val);return val+"bbb"}).catch(val=>console.log("err",val)).then(()=>{
	console.log("结束")
})


resolve/reject 创建一个普通promise 和 错误的promise

class PromiseA {
	constructor(x) {
		this.code = "dengdai"
		this.val = null
		this.err = null
		this.valf = []
		this.errf = []
		let a = (val) => {
			queueMicrotask(
				() => {
					this.code = "going"
					this.val = val
					this.valf.forEach(val => val())
				})
		}
		let b = (err) => {
			queueMicrotask(
				() => {
					this.code = "going"
					this.err = err
					this.errf.forEach(err => err())
				})
		}
		try {
			x(a, b)
		} catch (e) {
			//TODO handle the exception
			b(e)
		}

	}
	then(val, err) {
		err=err||(err=>{throw err})
		val=val||(val=>val)
		return new PromiseA((a, b) => {
				if (this.code == "dengdai") {
					if(val!=null){
						this.valf.push(() => {
							try {
								let vals = val(this.val)
								a(vals)
							} catch (e) {
								//TODO handle the exception
								b(e)
							}
						})
					}
					if(err!=null){
						this.errf.push(() => {
							try {
								let k = this.err								
								a(err(k))	
							} catch (e) {
								b(e)
							}
						})
					}
			} else if (this.code == "going") {
				if (this.val != null) {
					try {
						let e = this.val
						a(val(e))
					} catch (e) {
						//TODO handle the exception
						b(e)
					}

				} else {
					try {
						let e = this.err
						a(err(e))
					} catch (e) {
						//TODO handle the exception
						b(e)
					}

				}

			}


		})
}
catch(b){
	return this.then(undefined,b)
}
finally(or){
	return this.then(()=>{
		or()
	},()=>{
		or()
	})
}
static resolve(obj){
	return new PromiseA((a,b)=>{
		a(obj)
	})
}

static reject(str){
	return new PromiseA((a,b)=>{
		throw str
	})
}

}
all,allSettled
class PromiseA {
	constructor(x) {
		this.code = "dengdai"
		this.val = null
		this.err = null
		this.valf = []
		this.errf = []
		let a = (val) => {
			queueMicrotask(
				() => {
					this.code = "going"
					this.val = val
					this.valf.forEach(val => val())
				})
		}
		let b = (err) => {
			queueMicrotask(
				() => {
					this.code = "going"
					this.err = err
					this.errf.forEach(err => err())
				})
		}
		try {
			x(a, b)
		} catch (e) {
			//TODO handle the exception
			b(e)
		}

	}
	then(val, err) {
		err=err||(err=>{throw err})
		val=val||(val=>val)
		return new PromiseA((a, b) => {
				if (this.code == "dengdai") {
					if(val!=null){
						this.valf.push(() => {
							try {
								let vals = val(this.val)
								a(vals)
							} catch (e) {
								//TODO handle the exception
								b(e)
							}
						})
					}
					if(err!=null){
						this.errf.push(() => {
							try {
								let k = this.err								
								a(err(k))	
							} catch (e) {
								b(e)
							}
						})
					}
			} else if (this.code == "going") {
				if (this.val != null) {
					try {
						let e = this.val
						a(val(e))
					} catch (e) {
						//TODO handle the exception
						b(e)
					}

				} else {
					try {
						let e = this.err
						a(err(e))
					} catch (e) {
						//TODO handle the exception
						b(e)
					}

				}

			}


		})
}
catch(b){
	return this.then(undefined,b)
}
finally(or){
	return this.then(()=>{
		or()
	},()=>{
		or()
	})
}
static resolve(obj){
	return new PromiseA((a,b)=>{
		a(obj)
	})
}

static reject(str){
	return new PromiseA((a,b)=>{
		throw str
	})
}
static all(list){
	return new PromiseA((a,b)=>{
		let lists =[]
		list.forEach(val=>val.then(val=>{
			lists.push(val)
			if(lists.length==list.length){
				a(lists)
			}
		},err=>{
			b(err)
		}))
	})
}

static allSettled(list){
	return new PromiseA((a,b)=>{
		let lists = []
		list.forEach(val=>{
			val.then(vals=>{
				lists.push("code: 200 value:"+vals)
				if(list.length==lists.length){
					a(lists)
				}
			},err=>{
				lists.push("code: 400 value:"+err)
				if(list.length==lists.length){
					a(lists)
				}
			})
			
		})	
	})
}


}
let m = new PromiseA((res, err) => {
	setTimeout(()=>{
		res(11234)
	},1000)
	
})
let m1 = new PromiseA((res, err) => {
	setTimeout(()=>{
		res(1123)
	},2000)
})
let m2 = new PromiseA((res, err) => {
	throw "errpss"
})
// m.then(val=>val+"123").then(val=>{console.log(val);return val+"bbb"}).catch(val=>console.log("err",val)).then(()=>{
// 	console.log("结束")
// })

// let k = PromiseA.reject("hellow word").then(val=>console.log(val),err=>console.log())
let k = PromiseA.allSettled([m,m2,m1]).then(val=>console.log(val))
竞速 race
static race(list){
	return new PromiseA((a,b)=>{
		list.forEach(val=>{
			val.then(val=>{
				a(val)
			},err=>{
				b(err)
			})
		})
	})
}
any方法
static any(list) {
		return new PromiseA((a, b) => {
			let lists = []
			let sb = []
			list.forEach(val => {
					val.then(val => {
							if (lists.length == 0) {
								a(val)
								lists.push(1)
							}
						}, err => {
							sb.push(err)
							if (sb.length == list.length) {
								b(new AggregateError(sb))
							}
						})
					})
			})
	}

let k = PromiseA.any([m2, m2, m2]).then(val => console.log(val), err => console.log(err.errors))

调用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自信小老头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值