Promise原理理解

Promise

1.基本结构:

const promise = new Promise(handler)

handler:(resolve, reject) => {}

promise.then(onFulfilled, onRejected).then(onFulfilled, onRejected)

2.状态:

promise存在三种状态

  • pending

  • fulfilled

  • rejected

状态只能由 Pending 变为 Fulfilled 或由 Pending 变为 Rejected ,且状态改变之后不会在发生变化,会一直保持这个状态。

handler函数包含 resolvereject 两个参数,它们是两个函数,可以用于改变 Promise 的状态和传入 Promise 的值

3.构思源码需要注意的点:

对于handler:handler必须是函数 需要做类型判断 非函数类型则抛出错误

对于resolve和reject:需要做两件事,一个是状态修改,另一个是值的传递,另外需要注意确保函数只能执行一次

resolve(val) {
    if(this.status !== 'PENDING') return // 确保只能执行一次
    this.status = 'FULFILLED' // 状态修改
    this.value = val // 收集传进来的值
}
reject(err) {
    if(this.status !== 'PENDING') return
    this.status = 'REJECTED'
    this.value = err
}

对于then以及其参数onFulfilled和onRejected:

  1. 当resolve或reject执行后状态发生了改变才会执行then以及内部对应的onFulfilled或者onRejected

  2. 需要注意onFulfilled和onRejected必须是函数 否则会被忽略

  3. then()会返回一个promise 这个是链式调用的基础

  4. then中的onFulfilled或者onRejected需要有返回值 才能使得 下一个then中的onFulfilled或者onRejected的参数有值,没有返回值则为undefined

  5. 如果onFulfilled或者onRejected有返回值

    1. 如果返回值不是Promise :下一个promise的then会立即执行(状态为fulfilled)返回的值作为这个then里面onFulfilled或者onRejected的参数

      let promise1 = new Promise((resolve, reject) => {
          setTimeout(() => {
              resolve()
          }, 1000)
      })
      promise2 = promise1.then(res => {
          console.log('promise1的状态变为fulfilled') // 1s后执行
          return '这是给promise2的'
      })
      promise2.then(res => {
          console.log(res) // 打印 这是给promise2的 在promise1的then执行完会立即执行
      })

    2. 如果返回值是Promise:该返回的promise相当于下一个promise,下一个promise的then会在该返回值的state变化后执行,then中onFulfilled或者onRejected的参数也是返回的promise中进行传递的

      let promise1 = new Promise((resolve, reject) => {
          setTimeout(() => {
              resolve("这是传给promise1的");
          }, 1000);
      });
      let promise2 = promise1.then((res) => {
          console.log(res, "promise1的回调执行拉"); // 1s后执行
          return new Promise((resolve, reject) => {
              setTimeout(() => {
                  resolve("这是传给promise2的");
              }, 2000);
          });
      }); 
      promise2.then((res) => {
         console.log(res, "promise2的回调执行拉"); // 在promise1的then执行完2s后执行 打印 这是传给promise2的, promise2的回调执行拉
      });

4.简易版Promise

class MyPromise{
    const isFunction = variable => typeof variable === 'function'
    constructor(handler) {
        // handler必须是函数 否则抛错
        if (!isFunction(handle)) {
      		throw new Error('MyPromise must accept a function as a parameter')
    	}
        
	// 首先声明变量用来存储状态以及传递的值
        this.status = 'PENDING'
        this.resolveValue = undefined
        this.rejectValue = undefined
        // 这两个数组后面解释其作用
        this.onFulfilledList = []
        this.onRejectedList = []
        
        // 定义resolve以及reject
        resolve(val) {
            if(this.status !== 'PENDING') return // 确保只能执行一次resolve或者reject
            this.status = 'FULFILLED' // 状态修改
            this.resolveValue = val // 收集传进来的值
	}
        reject(err) {
            if(this.status !== 'PENDING') return
            this.status = 'REJECTED'
            this.rejectValue = err
	}
        
        // 执行handler
        try{
            /*
             * 注意:易错点 这里必须通过bind对resolve和reject的this绑定为此promise实例
             * 否则在resolve和reject内部无法通过this获取到此promise实例的status和resolveValue/rejectValue
             */
            handler(this.resolve.bind(this), this.reject.bind(this))
        }catch(err){
            this.reject(err)
        }
    }
}

// 定义then
MyPromise.prototype.then(onFulfilled, onRejected) {
    switch(this.status){
        case 'FULFILLED':{
            onFulfilled(this.resolveValue)
        }
        case 'REJECTED':{
            onRejected(this.rejectValue)
        }
    }
}

5.then的完善

上诉简易版只是最基本的promise雏形,下面将对其进行完善

完善点1:

如果handler中的resolve或者reject函数被包裹在异步方法中,会出现先执行then后执行resolve或者reject的情况(此时状态还是pending,所以then中的回调均不会执行)

修正如下:

// 新增两个变量用来存储回调函数
this.onFulfilledList = []
this.onRejectedList = []
// then的修正
MyPromise.prototype.then(onFulfilled, onRejected) {
    switch(this.status){
        case 'FULFILLED':{
            onFulfilled(this.resolveValue)
            break
        }
        case 'REJECTED':{
            onRejected(this.rejectValue)
            break
        }
        // 将回调都存储到回调数组里面
        case 'PENDING': {
            this.onFulfilledList.push(() => {
		onFulfilled(this.resolveValue)
            })
            this.onRejectedList.push(() => {
		onRejected(this.rejectValue)
            })
	}
    }
}
// resolve和reject的修正
resolve(val) {
    if(this.status !== 'PENDING') return // 确保只能执行一次resolve或者reject
    this.status = 'FULFILLED' // 状态修改
    this.resolveValue = val // 收集传进来的值
    // 执行回调
    this.onFulfilledList.forEach((cb) => {
	cb()
    })
}
reject(err) {
    if(this.status !== 'PENDING') return
    this.status = 'REJECTED'
    this.rejectValue = err
    // 执行回调
    this.onRejectedList.forEach((cb) => {
	cb()
    })
}

完善点2:

完成then的链式调用,对应上面then需要注意的2、3、4、5点

MyPromise.prototype.then(onFulfilled, onRejected) {
    // 对应第3点返回新的promise实例以实现链式调用
    return promise2 = new MyPromise((resolve, reject) => {
        // 需要注意 修正后的回调不仅会执行自己promise的回调 还会干预所返回的promise的状态
        
        // 修正后的成功回调
        fixedOnfulfilled(value) {
            // 执行自己promise的回调看是否报错 如果报错直接修改下一个promise的状态为rejected
			try {
				// 判断自己promise的回调是否为函数 不是函数直接传递值给下一个promise(对应第2点)
                if(!isFunction(onFulfilled)) {
					resolve(value)
                }else {
					let res = onFulfilled(value) // 执行自己的回调并收集返回值
                    // 判断返回值是否为promise 对应第5点
                    if(res instanceof MyPromise) {
						// 返回值是promise
                        // 这里不太好理解 实际是相当于将下一个promise的resolve和reject当作返回promise(res)的回调 执行返回promise回调的同时 修改下一个promise的状态 具体传递的值 是由返回promise内部决定的
                        res.then((v) => {resolve(v)}, (err) => {reject(err)}
                    }else{
                        // 返回值不是promise
                        resolve(res)
                    }
                }
                
            }catch(err) {
                // 修改下一个promise的状态为rejected
				reject(err)
            }
        }
        
        // 修正后的失败回调
        fixedOnRejected(err) {
            // 执行自己promise的回调看是否报错 如果报错直接修改下一个promise的状态为rejected
			try {
				// 判断自己promise的回调是否为函数 不是函数直接传递值给下一个promise(对应第2点)
                if(!isFunction(onRejected)) {
					reject(err)
                }else {
					let res = onRejected(err) // 执行自己的回调并收集返回值
                    // 判断返回值是否为promise 对应第5点
                    if(res instanceof MyPromise) {
						// 返回值是promise
                        // 这里不太好理解 实际是相当于将下一个promise的resolve和reject当作返回promise(res)的回调 执行返回promise回调的同时 修改下一个promise的状态 具体传递的值 是由返回promise内部决定的
                        res.then((v) => {resolve(v)}, (err) => {reject(err)}
                    }else{
                        // 返回值不是promise
                        reject(err)
                    }
                }
                
            }catch(err) {
                // 修改下一个promise的状态为rejected
				reject(err)
            }
        }
        
        // 根据状态执行修正后的回调
        switch(this.status){
            case 'fulfilled':{
                fixedOnfulfilled(this.resolveValue)
                break
            }
            case 'rejected':{
                fixedOnRejected(this.rejectValue)
                break
        	}
            // 将回调都存储起来
            case 'pending': {
                this.onFulfilledList.push(() => {
                    fixedOnfulfilled(this.resolveValue)
                })
                this.onRejectedList.push(() => {
                    fixedOnRejected(this.rejectValue)
                })
            }
    	}
    })
}

完善点3:

异步修正

then中回调函数中是以异步的方式执行的

switch(this.status){
	case 'FULFILLED':{
        // 将成功回调放入事件队列中
        setTimeOut(() => {
			fixedOnfulfilled(this.resolveValue)
        })
        break
    }
    case 'REJECTED':{
        // 将失败回调放入事件队列中
        setTimeOut(() => {
			fixedOnRejected(this.rejectValue)
        })
        break
    }
    case 'PENDING': {
        this.onFulfilledList.push(() => {
            fixedOnfulfilled(this.resolveValue)
        })
        this.onRejectedList.push(() => {
            fixedOnRejected(this.rejectValue)
        })
    }
}

resolve和reject在事件循环末尾执行,因此也需要添加异步

resolve(val) {
    setTimeOut(() => {
		if(this.status !== 'PENDING') return // 确保只能执行一次resolve或者reject
		this.status = 'FULFILLED' // 状态修改
		this.resolveValue = val // 收集传进来的值
    	// 执行回调
    	this.onFulfilledList.forEach((cb) => {
			cb()
    	})
    })
}
reject(err) {
    setTimeOut(() => {
		if(this.status !== 'PENDING') return
    	this.status = 'REJECTED'
    	this.rejectValue = err
    	// 执行回调
    	this.onFulfilledList.forEach((cb) => {
			cb()
    	})
    })
}

6.最终代码

class MyPromise{
    const isFunction = variable => typeof variable === 'function'
	constructor(handler) {
        if (!isFunction(handle)) {
      		throw new Error('MyPromise must accept a function as a parameter')
    	}
        
        this.status = 'PENDING'
        this.resolveValue = undefined
        this.rejectValue = undefined
        this.onFulfilledList = []
        this.onRejectedList = []
        
        resolve(val) {
    		setTimeOut(() => {
				if(this.status !== 'PENDING') return
				this.status = 'FULFILLED' 
				this.resolveValue = val 
    			this.onFulfilledList.forEach((cb) => {
					cb()
    			})
    		})
		}
		reject(err) {
    		setTimeOut(() => {
				if(this.status !== 'PENDING') return
    			this.status = 'REJECTED'
    			this.rejectValue = err
    			this.onFulfilledList.forEach((cb) => {
					cb()
    			})
    		})
		}
        
        try{
			handler(this.resolve.bind(this), this.reject.bind(this))
        }catch(err){
			this.reject(err)
        }
    }
}

MyPromise.prototype.then(onFulfilled, onRejected) {
    return promise2 = new MyPromise((resolve, reject) => {
        
        fixedOnfulfilled(value) {
			try {
                if(!isFunction(onFulfilled)) {
					resolve(value)
                }else {
					let res = onFulfilled(value) 
                    if(res instanceof MyPromise) {
                        res.then(resolve, reject)
                    }else{
                        resolve(value)
                    }
                }
            }catch(err) {
				reject(err)
            }
        }
        
        fixedOnRejected(err) {
			try {
                if(!isFunction(onRejected)) {
					reject(err)
                }else {
					let res = onRejected(err)
                    if(res instanceof MyPromise) {
                        res.then(resolve, reject)
                    }else{
                        reject(err)
                    }
                }
                
            }catch(err) {
				reject(err)
            }
        }
        
        switch(this.status){
			case 'FULFILLED':{
        		setTimeOut(() => {
					fixedOnfulfilled(this.resolveValue)
        		})
        		break
    		}		
    		case 'REJECTED':{
        		setTimeOut(() => {
					fixedOnRejected(this.rejectValue)
        		})
        		break
    		}
    		case 'PENDING': {
        		this.onFulfilledList.push(() => {
           		    fixedOnfulfilled(this.resolveValue)
        		})
        		this.onRejectedList.push(() => {
            		fixedOnRejected(this.rejectValue)
        		})
    		}
		}
    })
}

猜你喜欢

转载自blog.csdn.net/m0_64023259/article/details/123463359
今日推荐