从零手撕Promise,掌握Promise的实现原理(2)之基础版本的promise实现

1,253 阅读2分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」。

上篇文章介绍到Promise的基本结构,如下

建议阅读一下上篇文章,文章地址

  const PENDING = 'pending'
  const FULFILLED = 'fulfilled'
  const REJECTED = 'rejected'

  class Promise{
    constructor(executor){

      this.state = PENDING
      this.value = undefined
      this.reason = undefined

      const resolve = (value) => {

      }

      const reject = (reason) => {

      }

        executor(resolve,reject)

    }

    then(onFulfilled, onRejected){


    }
  }

实现基础版本的Promise

resolve与reject实现

    1. 如果调用resolve会让状态变成成功态,调用reject会让状态变成失败态,并且状态改变后再次调用resolvereject将不再起作用.
    • resolvereject函数实现
         const resolve = (value) => {
           if (this.state === PENDING) {
               this.value = value
               this.state = FULFILLED
           }
         }
      
         const reject = (reason) => {
           if (this.state === PENDING) {
             this.reason = reason
             this.state = REJECTED
           }
         }
      

then方法实现

    1. new Promise会产生一个promise实例, promise实例拥有一个then方法,第一个参数是成功的回调(onFulfilled),第二个参数是失败的回调(onRejected).当我们调用实例上的then方法时,如果promise实例是成功的状态,则会调用onFulfilled,参数为promise实例成功的值(value);如果promise实例是失败的状态,则会调用onRejected,参数为promise实例失败的原因(reason)。
    • then方法初步实现
         then(onFulfilled, onRejected){
           if (this.state === FULFILLED) {
              onFulfilled(this.value)
           }
      
          if (this.state === REJECTED) {
            onRejected(this.reason)
          }
         } 
      
    1. 但是这样的话问题又来了,当我像如下这样new一个Promise呢。很明显当我调用实例p上的then方法的时候,实例p的状态还不确定。
        let p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('成功')
            }, 1000);
        })
        p.then(value => {
            console.log(value, '成功')
        }, reason => {
            console.log(reason, '失败')
        })
    
    1. 对于上面这个问题我们需要改造我们的then方法,当我们调用then方法的时候,如果此时promise实例的状态还是pending状态,我们需要把onFulfilled函数与onRejected函数存起来,当promise实例的状态改变时再去调用,因此我们还需要改造resolvereject函数。
    • 此外new Promise的时候,需要传入一个执行函数executor , executor默认会立即执行,假如执行过程中出错,那么我们需要调用reject,将错误原因作为参数传进去,promise实例的状态将会改为失败。
    • 改造后的Promise,如下
        const PENDING = 'pending'
        const FULFILLED = 'fulfilled'
        const REJECTED = 'rejected'
    
        class Promise{
          constructor(executor){
    
            this.state = PENDING
            this.value = undefined
            this.reason = undefined
            //存放onFulfilled
            this.onResolvedCallbacks = []
            //存放onRejected
            this.onRejectedCallbacks = []
            const resolve = (value) => {
              if (this.state === PENDING) {
                this.value = value
                this.state = FULFILLED
                //promise实例状态改变后调用暂存的onFulfilled
                this.onResolvedCallbacks.forEach(fn => fn())
              }
            }
    
            const reject = (reason) => {
              if (this.state === PENDING) {
                this.reason = reason
                this.state = REJECTED
                //promise实例状态改变后调用的onRejected
                this.onRejectedCallbacks.forEach(fn => fn())
              }
            }
            try {
              executor(resolve,reject)
            } catch (error) {
              reject(error)
            }
          }
          then(onFulfilled, onRejected){
            if (this.state === FULFILLED) {
              onFulfilled(this.value)
            }
    
            if (this.state === REJECTED) {
              onRejected(this.reason)
            }
    
            if (this.state === PENDING) {
              //如果此时promise实例的状态还未确定,我们需要将onFulfilled与onRejected存起来,等到promise实例状态改变后再去调用
              this.onResolvedCallbacks.push(() => {
                onFulfilled(this.value)
              })
              this.onRejectedCallbacks.push(() => {
                onRejected(this.reason)
              })
            }
    
          }
        }
    
    • 到此时检验一下我们的promise
      let p = new Promise((resolve,reject) => {
        setTimeout(() => {
          resolve('成功')
        },1000)
      })
    
      p.then(value => {
        console.log('value',value);
      },reason => {
        console.log('reason',reason);
      })
    

    11-03.png

后续文章每天会持续完成

建议阅读一下上篇文章,文章地址