逐步分析Promise底层原理并掌握理解相应方法

152 阅读3分钟

第一步1.搭建Promise结构

promise起始状态为pending

调用resolve成功为solved 调用reject失败为rejected

返回的值包含 起始状态和值

class Promise {
    constructor(executor) {
        //先定义初始值
        const PromiseState = 'Pending'
        const PromiseResult = null
        //定义resolve函数 
        const resolve = (data) => {
            this.PromiseState = 'resolved'
            this.PromiseResult = data
        }
        //定义reject函数 
        const reject = (data) => {
            this.PromiseState = 'reject'
            this.PromiseResult = data
        }
    }
     executor(resolve, reject)
}

第二步 解决抛出错误问题

try {
    executor(resolve, reject)
} catch (e) {
    reject(e)
}

第三步 解决状态只能改变一次的问题

if (this.PromiseState !== 'Pending') return;

结合起来看一下 此时只缺少解决多个异步任务的问题

class Promise {
    constructor(executor) {
        //两个初始值
        this.PromiseState = 'Pending'
        this.PromiseResult = null
        //创建resolve函数
        const resolve = (data) => {
            //如果状态发生过改变直接返回
            if (this.PromiseState !== 'Pending') return;
            //改变两个属性值
            this.PromiseState = 'resolved'
            this.PromiseResult = data
        }
        //创建reject函数
        const reject = (data) => {
            //如果状态发生过改变直接返回
            if (this.PromiseState !== 'Pending') return;
            //改变两个属性值
            this.PromiseState = 'rejected'
            this.PromiseResult = data
        }
        //解决抛出错误
        try {
            executor(resolve, reject)
        } catch (e) {
            reject(e)
        }
    }
 }

第四步 添加then方法并添加成功和失败的回调

then(onResolved, onRejected) {
  return new Promise((resolve, reject) => {
        //成功的回调
       if (this.PromiseState == 'resolved') {
           onResolved()
       }
       //失败的回调
       if (this.PromiseState == 'rejected') {
           onRejected()
      }
   }
}

第四步 解决异步问题

如果Promise的起始状态为pending 我们需要将成功失败的回调存起来 等状态发生改变再去执行,因为考虑可能有多个then同时出现,所以我们采用数组的方式存起来

this.callback = []
if (this.PromiseState == 'Pending') {
    this.callback.push({
        onResolved,
        onRejected
    })
}
//这一步就是遍历回调(这一步是放在 )
 this.resolveCallBack.forEach(item => item.onResolved(val));

第五步 解决多个Promise嵌套的情况

      //成功的回调
   if (this.PromiseState == 'resolved') {
       //收集成功回调返回的结果
       let result = onResolved(this.PromiseResult)
       //如果返回的结果是一个Promise 则再执行一遍then方法 如果不是则返回结果
       if (result instanceof Promise) {
          result.then(v => { resolve(v) }, r => { reject(r) })
       } else {
           resolve(result)
       }
   }

第六步 解决抛出错误

      //成功的回调
   if (this.PromiseState == 'resolved') {
        try {
           let result =  onResolved(this.PromiseResult)
            if (result instanceof Promise) {
                 result.then(v => { resolve(v) }, r => { reject(r) })
        } else {
         resolve(result)
       }
     } catch (e) { reject(e) }
   }

整体结合起来看一下

class Promise {
    constructor(executor) {
        //定义初始值
        this.PromiseState = 'Pending'
        this.PromiseResult = null
        //存放成功的回调
        this.resolveCallBack = []
        //存放失败的回调
        this.rejectCallBack = []
        //创建resolve函数
        const resolve = (val) => {
            //对当前状态进行判断
            if (this.PromiseState !== 'Pending') return
            //赋值
            this.PromiseState = 'resolved'
            this.PromiseResult = val
            //遍历回调
             this.resolveCallBack.forEach(item => item.onResolved(val));
        }
        //创建reject函数
        const reject = (res) => {
            //对当前状态进行判断
            if (this.PromiseState !== 'Pending') return
            //赋值
            this.PromiseState = 'rejected'
            this.PromiseResult = res
            //遍历回调         
            this.rejectCallBack.forEach(item => item.onRejected(res));
        }
        try {
            executor(resolve, reject)
        } catch (error) {
            reject(error)
        }
    }
    then(onResolved, onRejected) {
        return new Promise((resolve, reject) => {
             //成功的回调
            if (this.PromiseState == 'resolved') {
                try {
                    let result =  onResolved(this.PromiseResult)
                    if (result instanceof Promise) {
                        result.then(v => { resolve(v) }, r => { reject(r) })
                     } else {
                         resolve(result)
                      }
                } catch (e) { reject(e) }
            }
             //失败的回调
            if (this.PromiseState == 'rejected') {
                try {
                    let result =  onRjected(this.PromiseResult)
                    if (result instanceof Promise) {
                        result.then(v => { resolve(v) }, r => { reject(r) })
                     } else {
                         resolve(result)
                      }
                } catch (e) { reject(e) }
            }
            //状态未改变
            if (this.PromiseState == 'Pending') {
                this.resolveCallBank.push( onResolved)
                this.rejectCallBank.push( onRejected)
            }
        })
    }

catch方法

    catch(onRejected) {
        return this.then(undefined, onRejected)
    }

其次就是resolved rejected all race 方法 就不拆开了

all和race方法传入的都是一个数组

区别在于 all 全部为成功 返回的结果才为成功 race 返回的值是第一个改变状态的值

    static resolve(value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then(v => { resolve(v) }, r => { reject(r) })
            } else {
                resolve(value)
            }
        })
    }
    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }
    static all = function (array) {
        return new Promise((resolve, reject) => {
            let num = 0
            let arr = []
            for (let i = 0; i < array.length; i++) {
                array[i].then(v => {
                    num++
                    arr[i] = v
                    if (num == array.length) resolve(arr)
                }, r => {
                    reject(r)
                })
            }
        })
    }
    static race = function (array) {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < array.length; i++) {
                array[i].then(v => {
                    resolve(v)
                }, r => {
                    reject(r)
                })
            }
        })
    }