从零手撕Promise,掌握Promise的实现原理(5)之then方法链式调用的进阶实现

339 阅读3分钟

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

传送门

从零手撕Promise,掌握Promise的实现原理(1)之promise基本结构的实现 从零手撕Promise,掌握Promise的实现原理(2)之基础版本的promise实现 从零手撕Promise,掌握Promise的实现原理(3)之回调地狱是什么 从零手撕Promise,掌握Promise的实现原理(4)之then方法链式调用的初步实现

回顾

经过上次的介绍我们的then方法已经有一个初步的样子了,我们的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函数执行过程中出错,将会导致Promise失败
      executor(resolve,reject)
    } catch (error) {
      reject(error)
    }
  }
  then(onFulfilled, onRejected){

    let promise = new Promise((resolve, reject) => {
        
        switch(this.state){
          case FULFILLED:
              try{
                let x = onFulfilled(this.value)
                resolve(x)
              } catch(e){
                reject(e)
              }   
              break
          case REJECTED:
              try{
                let x = onRejected(this.reason)
                resolve(x)
              } catch(e){
                reject(e)
              }   
              break
          default:
            this.onResolvedCallbacks.push(() => {
              try{
                let x = onFulfilled(this.value)
                resolve(x)
              } catch(e){
                reject(e)
              }
            })
            this.onRejectedCallbacks.push(() => {
              try{
                let x = onRejected(this.reason)
                resolve(x)
              } catch(e){
                reject(e)
              }
            })
        }
      
    })
    return promise
  }
}

then方法返回的是Promise

  • 如果调用Promise实例的then方法返回的是一个Promise,那么我们需要判断这个Promise的状态.
    • 如果Promise是成功的,就将成功的结果,传递到then方法返回的Peomise的成功回调当中;
    • 如果Promise是失败的,就将失败的原因,传递到then方法返回的Peomise的失败回调当中。
  • 那么我们的then方法,就不能简单的直接将其回调的返回值,传递到这个then方法要返回的Promise中了.
  • 这里我们通过一个方法来解析then方法回调的返回值,我们称这个方法为resolvePromise, 这个方法不是Promise这个类上的方法.
  • 对于resolvePromise,这个方法的作用就是解析then方法中回调函数的返回值,根据返回值是什么,来改变then方法中将要返回的Promise的状态.
  • 因此我们需要四个参数分别是,then方法要返回的Promisethen方法中回调函数的返回值x、将要返回的promiseresolve函数与reject函数。
  • 相应的then方法也要进行改造。
const resolvePromise = (promise, x, resolve, reject) => {

}

then(onFulfilled, onRejected){

    let promise = new Promise((resolve, reject) => {
        
        switch(this.state){
          case FULFILLED:
              try{
                let x = onFulfilled(this.value)
                //这里就不能简单的resolve(x)了,而要通过resolvePromise去解析返回值
                resolvePromise(promise, x, resolve, reject)
              } catch(e){
                reject(e)
              }   
              break
          case REJECTED:
              try{
                let x = onRejected(this.reason)
                resolvePromise(promise, x, resolve, reject)
              } catch(e){
                reject(e)
              }   
              break
          default:
            this.onResolvedCallbacks.push(() => {
              try{
                let x = onFulfilled(this.value)
                resolvePromise(promise, x, resolve, reject)
              } catch(e){
                reject(e)
              }
            })
            this.onRejectedCallbacks.push(() => {
              try{
                let x = onRejected(this.reason)
                resolvePromise(promise, x, resolve, reject)
              } catch(e){
                reject(e)
              }
            })
        }
      
    })
    return promise
  }

到此我们的完整的Promise,长这样

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const resolvePromise = (promise, x, resolve, reject) => {

}
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函数执行过程中出错,将会导致Promise失败
      executor(resolve,reject)
    } catch (error) {
      reject(error)
    }
  }
  then(onFulfilled, onRejected){

    let promise = new Promise((resolve, reject) => {
        
        switch(this.state){
          case FULFILLED:
              try{
                let x = onFulfilled(this.value)
                resolvePromise(promise, x, resolve, reject)
              } catch(e){
                reject(e)
              }   
              break
          case REJECTED:
              try{
                let x = onRejected(this.reason)
                resolvePromise(promise, x, resolve, reject)
              } catch(e){
                reject(e)
              }   
              break
          default:
            this.onResolvedCallbacks.push(() => {
              try{
                let x = onFulfilled(this.value)
                resolvePromise(promise, x, resolve, reject)
              } catch(e){
                reject(e)
              }
            })
            this.onRejectedCallbacks.push(() => {
              try{
                let x = onRejected(this.reason)
                resolvePromise(promise, x, resolve, reject)
              } catch(e){
                reject(e)
              }
            })
        }
      
    })
    return promise
  }
}

为什么then方法中的回调(onFulfilled、onRejected)是微任务?

思考下面图片中的问题

11-06-1.png

resolvePromise的实现留给下一篇文章

传送门

从零手撕Promise,掌握Promise的实现原理(1)之promise基本结构的实现 从零手撕Promise,掌握Promise的实现原理(2)之基础版本的promise实现 从零手撕Promise,掌握Promise的实现原理(3)之回调地狱是什么 从零手撕Promise,掌握Promise的实现原理(4)之then方法链式调用的初步实现