Promise实现原理

116 阅读2分钟

promise如何实现?最近研究了几天,研究明白了 原来是这样

首先完成同步下的then方法,promise是根据传入的函数中,成功或者失败进行判断,然后执行代码,所以我们进行如下封装,then是对正确或者错误的结果进行执行,所以我们只需要当所有then执行结束后调用即可,使用微任务来解决

class PromiseA{
	constructor(x){
		this.code="await"
		this.vals=[]
		this.errs=[]
		this.val = null
		this.err = null
		const trues= (val)=>{
			queueMicrotask(()=>{
				this.val = val
				this.code="going"
				this.vals.forEach(vals=>{
					vals(this.val)
				})
			})
		}
		const falses = ()=>{
			queueMicrotask(()=>{
				this.err = err
				this.code="going"
				this.vals.forEach(errs=>{
					vals(this.err)
				})
			})
		}
		x(trues,falses)
	}
	then(vals,errs){
		if(this.code=="await"){
			this.vals.push(vals)
			this.errs.push(errs)
		}
	}
	
}

let k = new PromiseA((a,b)=>{
	a(111)
})
k.then(val=>console.log(val))

ok,发现可以输出,搞定了then的同步方法,然后解决异步方法

加入对code的另一个判断 基本可以解决

then(vals,errs){
		if(this.code=="await"){
			this.vals.push(vals)
			this.errs.push(errs)
		}
		if(this.code=="going"){
			if(this.val!=null){
				vals(this.val)
			}
			if(this.err!=null){
				errs(this.err)
			}
		}
	}

ok,下面解决then的链式调用问题 链式调用简单来理解就是then.then,那么如何可以链式调用呢? then的结果是一个promise就可以解决了。返回一个promise

then(vals, errs) {
		return new PromiseA((a, b) => {
			if (this.code == "await") {
				this.vals.push(val=>{
					a(vals(val))
				})
				this.errs.push(err=>{
					a(errs(err))
				})
			}
			if (this.code == "going") {
				if (this.val != null) {
					a(vals(this.val))
				}
				if (this.err != null) {
					a(errs(this.err))
				}
			}
		})
	}

基本解决链式调用 接下来进行边界条件判断

then(vals, errs) {
		vals = vals || (vals => vals)
		errs = errs || (errs => errs)
		return new PromiseA((a, b) => {
			if (this.code == "await") {
				this.vals.push(val => {
					try {
						a(vals(val))
					} catch (e) {
						b(e)
					}
				})
				this.errs.push(err => {
					try {
						console.log(err)
						a(errs(err))
					} catch (e) {

						b(e)
					}
				})

			}
			if (this.code == "going") {
				if (this.val != null) {
					try {
						a(vals(this.val))
					} catch (e) {
						b(e)
					}
				}
				if (this.err != null) {
					try {
						a(errs(this.err))
					} catch (e) {
						b(e)
					}

				}


			}
		})
	}

搞定then catch就很简单了

catch(err){
	this.then(null,err)
}

相应的其他方法就太简单了

        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)
					}
				})

			})
		})
	}

	static race(list) {
		return new PromiseA((a, b) => {
			list.forEach(val => {
				val.then(val => {
					a(val)
				}, err => {
					b(err)
				})
			})
		})
	}
	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))
							}
						})
					})
			})
	}

搞定 又研究一天 草