手写promise 中then catch finally以及静态方法resolve,reject,all,allSettled,race

  • 初始化 promise
// 定义三种状态
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECT = 'reject'

class MyPromise {
  constructor(executor){
    this.status = PROMISE_STATUS_PENDING  // 初始化为pending状态
    this.value = undefined // 存储成功时候的值
    this.reason = undefined  // 存储失败时候的值
    const resolve = (value)=>{
      // 当状态为pending时 更改为成功状态
      if(this.status === PROMISE_STATUS_PENDING){
        this.status = PROMISE_STATUS_FULFILLED
        this.value = value // 保存成功返回的值
         console.log('resolve:',value)
      }
     
    }
    const reject = (reason)=>{
      // 当状态为pending时 更改为失败状态
      if(this.status === PROMISE_STATUS_PENDING){
        this.status = PROMISE_STATUS_REJECT
        this.reason = reason // 保存失败返回的值
        console.log('reject:',reason)
      }
    }
    executor(resolve,reject)
  }
}

// new 自己定义的promiase 
const promise = new MyPromise((resolve,reject)=>{
  // console.log('函数被直接调用')
  resolve(111)
})
  • 增加then方法调用
// ... 省略上面已经定义过的东西,只写关键代码 (...表示省略的重复定义)
class MyPromise {
  constructor(executor){
    // ...
    const resolve = (value)=>{
      // 当状态为pending时 更改为成功状态
      if(this.status === PROMISE_STATUS_PENDING){
        // 建立一个微任务,保证promise.then先执行,才能调用到this.onFulfilled函数,否则报this.onFulfilled不是一个函数
        // 也可以使用setTimeout(宏任务),queueMicrotask 是 微任务,当前回合下就能执行
        queueMicrotask(()=>{
          this.status = PROMISE_STATUS_FULFILLED
          this.value = value // 保存成功返回的值
          console.log('resolve:',value)
          this.onFulfilled(this.value)
        })
      }
     
    }
    const reject = (reason)=>{
      // 当状态为pending时 更改为失败状态
      if(this.status === PROMISE_STATUS_PENDING){
        // 建立一个微任务,保证promise.then先执行,才能调用到this.onRejected函数,否则报this.onRejected不是一个函数
        // 也可以使用setTimeout(宏任务),queueMicrotask 是 微任务,当前回合下就能执行
        queueMicrotask(()=>{
          this.status = PROMISE_STATUS_REJECT
          this.reason = reason // 保存失败返回的值
          console.log('reject:',reason)
          this.onRejected(this.reason)
        })
      }
    }
    executor(resolve,reject)
  }

  then(onFulfilled,onRejected){
    this.onFulfilled = onFulfilled
    this.onRejected = onRejected
  }
}

const promise = new MyPromise((resolve,reject)=>{
  resolve(111)
  // reject(444)
})

promise.then(res=>{
  console.log('res:',res)
},err=>{
    
})
  • 上述代码,存在问题,如:用户重复使用promise,则只会执行最后一次promise中传递的函数,后面不会执行

问题事例:

const promise = new MyPromise((resolve,reject)=>{
  resolve(111)
  // reject(444)
})

// 第一次调用
promise.then(res=>{
  console.log('res:',res)
},err=>{
    
})

// 第二次调用
promise.then(res=>{
  console.log('res2:',res)
},err=>{
    
})

解决办法:增加两个callback数组,分别存放成功,失败的函数,后面循环调用执行,关键代码如下:

class MyPromise {
  constructor(executor){
    // ...
    this.onFulfilledCallBack = []
    this.onRejectCallBack = []
    const resolve = (value)=>{
      // 当状态为pending时 更改为成功状态
      if(this.status === PROMISE_STATUS_PENDING){
        queueMicrotask(()=>{
        // queueMicrotask 会重启一个微任务执行,需要判断status状态不是pending时,则不往下执行
          if(this.status !== PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_FULFILLED
          this.value = value // 保存成功返回的值
          // 循环调用成功时的回掉
          this.onFulfilledCallBack.forEach(fn=>{
            fn(this.value)
          })
        })
      }
     
    }
    const reject = (reason)=>{
      // 当状态为pending时 更改为失败状态
      if(this.status === PROMISE_STATUS_PENDING){
        queueMicrotask(()=>{
        // queueMicrotask 会重启一个微任务执行,需要判断status状态不是pending时,则不往下执行
          if(this.status !== PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_REJECT
          this.reason = reason // 保存失败返回的值
          // 循环调用失败时的回掉
          this.onRejectCallBack.forEach(fn=>{
            fn(this.reason)
          })
        })
      }
    }
    executor(resolve,reject)
  }

  then(onFulfilled,onRejected){
    // 将成功和失败回掉保存到callBack函数中
    this.onFulfilledCallBack.push(onFulfilled)
    this.onRejectCallBack.push(onRejected)
  }
}

const promise = new MyPromise((resolve,reject)=>{
  resolve(111)
  // reject(444)
})

promise.then(res=>{
  console.log('res:',res)
})

promise.then(res2=>{
  console.log('res2:',res2)
})
  • 当有setTimeout函数延迟执行时,上述代码不会执行setTimeout里的promise语句,如下:

promise.then(res=>{
  console.log('res:',res)
})
// promise确定了状态 即不会执行setTimeout
setTimeout(()=>{
    promise.then(res=>{
      console.log('res:',res)
    })
},1000)

原因:再执行非setTimeout中promise后,status会变成fulfilled状态,status成了一种已确认的状态。所以修改then如下:

  then(onFulfilled,onRejected){
    console.log('this.status:',this.status)
    // 状态若是成功,则直接执行
    if(this.status === PROMISE_STATUS_FULFILLED && onFulfilled){
      onFulfilled(this.value)
    }
    // 状态若是失败,则直接执行
    if(this.status === PROMISE_STATUS_REJECT && onRejected){
      onRejected(this.reason)
    }
    // 将成功和失败回掉保存到callBack函数中
    if(this.status === PROMISE_STATUS_PENDING){
      this.onFulfilledCallBack.push(onFulfilled)
      this.onRejectCallBack.push(onRejected)
    }
    
  }
  • 解决then链式调用问题:如下实例
promise.then(res=>{
  console.log('res:',res)
}).then(res1=>{
  // 此then 调用会报错
  console.log('res1:',res)
})

原因:上面代码在调用一次then后,没有返回promise格式,导致在then链式调用会进行报错,then函数改动如下:

then(onFulfilled,onRejected){
    console.log('this.status:',this.status)
    return new MyPromise((resolve,reject)=>{
       // 状态若是成功,则直接执行
      if(this.status === PROMISE_STATUS_FULFILLED && onFulfilled){
        // 直接调用onFulfilled函数,resolve返回结果
        const value = onFulfilled(this.value)
        resolve(value)
      }
      // 状态若是失败,则直接执行
      if(this.status === PROMISE_STATUS_REJECT && onRejected){
      // 直接调用onRejected函数,虽说是reject
        const reason = onRejected(this.reason)
        resolve(reason)
      }
      // 将成功和失败回掉保存到callBack函数中
      if(this.status === PROMISE_STATUS_PENDING){
        this.onFulfilledCallBack.push(()=>{
          const value = onFulfilled(this.value)
          resolve(value)
        })
        this.onRejectCallBack.push(()=>{
          const reject = onRejected(this.reason)
          resolve(reject)
        })
      }
    })
  }
  • 异常处理,如在调用中抛出throw new Error()场景,实例代码如下:
// 实例1
const promise = new MyPromise((resolve,reject)=>{
  // 直接抛出异常
  throw new Error(' 直接 抛出 异常')
})

// 实例2 resolve中抛出异常
promise.then(res=>{
  console.log('res:',res)
  throw new Error('err message')
},err=>{
  console.log('err:',err)
}).then(res1=>{
  console.log('res1:',res1)
},err1=>{
  console.log('err1:',err1)
})

// 实例3 reject中抛出异常
promise.then(res=>{
  console.log('res:',res)
},err=>{
  console.log('err:',err)
  throw new Error('err message')
}).then(res1=>{
  console.log('res1:',res1)
},err1=>{
  console.log('err1:',err1)
})

解决办法:在代码函数调用中增加try catch 处理

// 工具函数
function execFnWithCatchError(execFn,value,resolve,reject){
  try{
    const result = execFn(value)
    resolve(result)
  }
  catch(err){
    reject(err)
  }
}

// then 方法修改为:
then(onFulfilled,onRejected){
    console.log('this.status:',this.status)
    return new MyPromise((resolve,reject)=>{
       // 状态若是成功,则直接执行
      if(this.status === PROMISE_STATUS_FULFILLED && onFulfilled){
        // 调用封装的try catch 函数
        execFnWithCatchError(onFulfilled,this.value,resolve,reject)
      }
      // 状态若是失败,则直接执行
      if(this.status === PROMISE_STATUS_REJECT && onRejected){
         // 调用封装的try catch 函数
        execFnWithCatchError(onRejected,this.reason,resolve,reject)
      }
      // 将成功和失败回掉保存到callBack函数中
      if(this.status === PROMISE_STATUS_PENDING){
        this.onFulfilledCallBack.push(()=>{
          // 调用封装的try catch 函数
          execFnWithCatchError(onFulfilled,this.value,resolve,reject)
        })
        this.onRejectCallBack.push(()=>{
           // 调用封装的try catch 函数
          execFnWithCatchError(onRejected,this.reason,resolve,reject)
        })
      }
    })
  }
  • 实现catch 方法
// 实例调用如下:
promise.then(res=>{
  console.log('res:',res)
}).catch(err1=>{
  console.log('catch err:',err1)
})

// 增加catch方法
catch(onRejected){
    // 可以直接调用then方法,把onFulfilled方法设置为undefined
    // 修改then方法,当onFulfilled为undefined时,返回一个throw err 报错,流程走到下一步
    this.then(undefined,onRejected)
}

// then方法也需要配合改造
then(onFulfilled,onRejected){
    // 处理onRejected为undefined的时候
    const defaultOnRejected = ((err)=>{throw err})
    onRejected = onRejected || defaultOnRejected
    return new MyPromise((resolve,reject)=>{
       // 状态若是成功,则直接执行
      if(this.status === PROMISE_STATUS_FULFILLED){
        // 调用封装的try catch 函数
        execFnWithCatchError(onFulfilled,this.value,resolve,reject)
      }
      // 状态若是失败,则直接执行
      if(this.status === PROMISE_STATUS_REJECT){
         // 调用封装的try catch 函数
        execFnWithCatchError(onRejected,this.reason,resolve,reject)
      }
      // 将成功和失败回掉保存到callBack函数中
      if(this.status === PROMISE_STATUS_PENDING){
      // 当 onFulfilled 不为undefined时,才缓存
        if(onFulfilled) this.onFulfilledCallBack.push(()=>{
          // 调用封装的try catch 函数
          execFnWithCatchError(onFulfilled,this.value,resolve,reject)
        })
        // 当 onRejected 不为undefined时,才缓存
        if(onRejected) this.onRejectCallBack.push(()=>{
           // 调用封装的try catch 函数
          execFnWithCatchError(onRejected,this.reason,resolve,reject)
        })
      }
    })
  }
  • 增加 finally 方法
// finally 调用
promise.then(res=>{
  console.log('res:',res)
}).catch(err1=>{
  console.log('catch err:',err1)
}).finally(()=>{
  console.log('finally')
})

// 添加finally 方法
// 无论是fulfilled还是rejected 都需要执行finally里的函数
finally(onFinally){
    // 直接调用 then 方法
    this.then(()=>{
      onFinally()
    },()=>{
      onFinally()
    })
}

// 在then方法中增加 onFulfilled 为undefined时的处理
then(onFulfilled,onRejected){
    // console.log('this.status:',onFulfilled)
    // 处理onRejected为undefined的时候
    const defaultOnRejected = (err)=>{throw err}
    onRejected = onRejected || defaultOnRejected

    <
上一篇:jmeter之并发和顺序执行与特殊线程组-第四天


下一篇:【LabVIEW FPGA入门】使用FPGA实现串行同步接口(SSI)