【手写Promise】第二篇:promise基本实现

230 阅读6分钟

一、实现思路

  • Promise 是一个类或函数;
  • 构造函数接收的参数是一个 excutor 函数;
  • 这个函数的参数是 resolve 和 reject 两个内部函数;
  • 构建 resolve 和 reject 并传入 excutor,并使之立即执行;
  • executor 参数是两个函数,用于描述 promise实例的状态;
    • resolve 表示成功,可以传入一个 value;
    • reject 表示失败,可以传入一个 reason;
  • 每个 Promise 实例都有一个 then 方法;
  • promise 一旦状态发生后,不能再更改
  • promise 有三种状态:成功态,失败态,等待态(默认)
  • 在 resolve 和 reject 中修改 status 状态;
  • Promise 类中包含 then 和 catch 等方法;
class myPromise {
  constructor(fun) {
    this.status = 'pending' // status:pending、fulfilled、rejected
    fun(this.resolve, this.reject) // 主体函数将会被立即执行
  }
  resolve() {}
  reject() {}
  then() {}
  catch() {}
}

二、三种状态切换和对应状态函数调用

// 声明 promise 三种状态
const PENDING = 'PENDING' // 等待态
const FULFILLED = 'FULFILLED' // 成功态
const REJECTED = 'REJECTED' // 失败态

class myPromise {
  // 通过 new 进行实例化时,传入 executor 执行器函数
  constructor(executor) {
    this.value = undefined // 成功的原因
    this.reason = undefined // 失败的原因
    this.state = PENDING // promise 状态,默认等待态
    // 成功 reslove 函数、失败reject函数,并传入executor
    const reslove = (value) => {
      // 等待态 --> 成功态
      if (this.state === PENDING) {
        this.value = value
        this.state = FULFILLED
      }
    }
    const reject = (reason) => {
      // 等待态 --> 失败态
      if (this.state === PENDING) {
        this.reason = reason
        this.state = REJECTED
      }
    }

    // 立即执行 executor 执行器函数,通过 try...catch... 进行异常捕捉;
    try {
      executor(reslove, reject)
    } catch (e) {
      reject(e) // 有异常,调用 reject 更新为失败态
    }
  }

  // 定义 then 方法:包含两个参数 onFulfilled 和 onRejected;
  // 根据 Promise 状态,执行 onFulfilled 或 onRejected;
  then(onFulfilled, onRejected) {
    // 成功态,调用 onFulfilled,传入成功 value
    if (this.state === DULFILLED) {
      onFulfilled(this.value)
    }
    // 失败态,执行 onRejected,传入失败 reason
    if (this.state === REJECTED) {
      onRejected(this.reason)
    }
  }
}

测试一下

let promise = new myPromise((resolve, reject)=>{
  console.log('promise')
  throw new Error("抛出错误");
})
promise.then((value)=>{
  console.log('success', value) 
},(reason)=>{
  console.log('err', reason)
})
console.log('ok')

运行结果

promise
err Error: 抛出错误
ok

很明显,没有按照预期的执行结果(先同步后异步),别着急,紧接着往下看。。。

三、对异步操作的支持

采用发布订阅的思想

  • 事件订阅:收集回调函数
constructor(executor) {
    this.onResolvedCallbacks = [] // 收集成功回调
    this.onRejectedCallbacks = [] // 收集失败回调
}
then(onFulfilled, onRejected) {
    if (this.state === PENDING) {
      this.onResolvedCallbacks.push(() => {
        onFulfilled(this.value) // 传入 value
      })
      this.onRejectedCallbacks.push(() => {
        onRejected(this.value) // 传入 value
      })
    }
 }
  • 事件发布:根据状态执行回调处理
 then(onFulfilled, onRejected) {
    if (this.state === PENDING) {
      this.onResolvedCallbacks.push(() => {
        onFulfilled(this.value) // 传入 value
      })
      this.onRejectedCallbacks.push(() => {
        onRejected(this.reason) // 传入 value
      })
    }
  }

四、promise的链式调用

链式调用分为几种情况

  1. 成功回调中,返回普通值

结论:成功回调中返回普通值,会进入下一个 then 的成功回调

let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    // 异步操作
    resolve('执行成功') // 进入成功回调处理
  }, 1000)
})

promise
  .then(
    (value) => {
      console.log('[then1-onFulfilled]', value)
      return 'then1-onFulfilled:' + value
      // return new Error()    // 返回普通值
      // return undefined      // 返回普通值
    },
    (reson) => {
      console.log('[then1-onRejected]', reson)
    }
  )
  .then(
    (value) => {
      console.log('[then2-onFulfilled]', value)
    },
    (reson) => {
      console.log('[then2-onRejected]', reson)
    }
  )
// 执行结果
// [then1-onFulfilled] 执行成功
// [then2-onFulfilled] then1-onFulfilled:执行成功
  1. 失败回调中,返回普通值

结论:失败回调中返回普通值,会进入下一个 then 的成功回调

let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('执行失败') // 进入失败回调处理
  }, 1000)
})

promise
  .then(
    (value) => {
      console.log('[then1-onFulfilled]', value)
      return 'then1-onFulfilled:' + value
    },
    (reson) => {
      console.log('[then1-onRejected]', reson)
      return 'then1-onRejected:' + reson // 返回普通值
      // return new Error()    // 返回普通值
      // return undefined      // 返回普通值
    }
  )
  .then(
    (value) => {
      console.log('[then2-onFulfilled]', value)
    },
    (reson) => {
      console.log('[then2-onRejected]', reson)
    }
  )

// [then1-onRejected] 执行失败
// [then2-onFulfilled] then1-onRejected:执行失败
  1. 成功回调中,抛出异常

结论:成功回调中抛出异常,会进入下一个 then 的失败回调

let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('执行成功')
  }, 1000)
})

promise
  .then(
    (value) => {
      console.log('[then1-onFulfilled]', value)
      throw new Error('抛出异常')
    },
    (reson) => {
      console.log('[then1-onRejected]', reson)
      return 'then1-onRejected:' + reson
    }
  )
  .then(
    (value) => {
      console.log('[then2-onFulfilled]', value)
    },
    (reson) => {
      console.log('[then2-onRejected]', reson)
    }
  )

// [then1-onFulfilled] 执行成功
// [then2-onRejected] Error: 抛出异常
  1. 失败回调中,抛出异常

结论:失败回调中抛出异常,会进入下一个 then 的失败回调

let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('执行失败')
  }, 1000)
})

promise
  .then(
    (value) => {
      console.log('[then1-onFulfilled]', value)
    },
    (reson) => {
      console.log('[then1-onRejected]', reson)
      throw new Error('抛出异常')
    }
  )
  .then(
    (value) => {
      console.log('[then2-onFulfilled]', value)
    },
    (reson) => {
      console.log('[then2-onRejected]', reson)
    }
  )

// [then1-onRejected] 执行失败
// [then2-onRejected] Error: 抛出异常
  1. executor 执行器中报错

结论:executor同步逻辑抛出异常,进入 then 失败处理

let promise = new Promise((resolve, reject) => {
  throw new Error('executor 同步报错') // 抛出异常
  resolve('处理成功') // 不会被执行
})
promise
  .then(
    (value) => {
      console.log('[then1-onFulfilled]', value)
    },
    (reson) => {
      console.log('[then1-onRejected]', reson)
    }
  )
  .then(
    (value) => {
      console.log('[then2-onFulfilled]', value)
    },
    (reson) => {
      console.log('[then2-onRejected]', reson)
    }
  )
// [then1-onRejected] Error: executor 同步报错
// [then2-onFulfilled] undefined
  1. 总结
    • Promise 的链式调用,当调用 then 方法后,将会返回一个全新的 promise 实例;
    • then 中方法(无论成功还是失败)返回普通值,都会做为下一次 then 的成功结果;
    • 执行器函数 和 then 中方法(无论成功还是失败)抛出异常,都会进入下一次 then 的失败结果;

代码实现

1. 获取 then 回调处理返回值

出现问题:作用域不同,无法获取x值

then(onFulfilled, onRejected) {
    if (this.state === PENDING) {
      this.onResolvedCallbacks.push(() => {
        let x = onFulfilled(this.value) // 传入 value
      })
      this.onRejectedCallbacks.push(() => {
        let x = onRejected(this.reason) // 传入 value
      })
    }
    // 成功态,调用 onFulfilled,传入成功 value
    if (this.state === FULFILLED) {
      // 拿到回调处理的返回值
      let x = onFulfilled(this.value)
    }
    // 失败态,执行 onRejected,传入失败 reason
    if (this.state === REJECTED) {
      let x = onRejected(this.reason)
    }
    // 包装回调处理的返回值 x ,成为一个全新的 Promise 实例
    let promise2 = new Promise((resolve, reject) => {
      // 问题:拿不到 x,不在一个作用域中
    })
    // 返回新的 promise 实例
    return promise2
 }
2. then 返回全新 promise

需要在 promise2 的 executor 执行器中拿到返回值解决上述问题

then(onFulfilled, onRejected) {
    let promise2 = new myPromise((reslove, reject) => {
      if (this.state === PENDING) {
        this.onResolvedCallbacks.push(() => {
          let x = onFulfilled(this.value) // 传入 value
          reslove(x)
        })
        this.onRejectedCallbacks.push(() => {
          let x = onRejected(this.reason) // 传入 value
          reslove(x)
        })
      }
      // 成功态,调用 onFulfilled,传入成功 value
      if (this.state === FULFILLED) {
        // 拿到回调处理的返回值
        let x = onFulfilled(this.value)
        reslove(x)
      }
      // 失败态,执行 onRejected,传入失败 reason
      if (this.state === REJECTED) {
        let x = onRejected(this.reason)
        reslove(x)
      }
    })
    // 返回新的 promise 实例
    return promise2
  }
3. 对异常的处理
then(onFulfilled, onRejected) {
    let promise2 = new myPromise((reslove, reject) => {
      if (this.state === PENDING) {
        this.onResolvedCallbacks.push(() => {
          try {
            let x = onFulfilled(this.value) // 传入 value
            reslove(x)
          } catch (error) {
            reject(error)
          }
        })
        this.onRejectedCallbacks.push(() => {
          try {
            let x = onRejected(this.reason) // 传入 value
            reslove(x)
          } catch (error) {
            reject(error)
          }
        })
      }
      // 成功态,调用 onFulfilled,传入成功 value
      if (this.state === FULFILLED) {
        // 拿到回调处理的返回值
        try {
          let x = onFulfilled(this.value) // 传入 value
          reslove(x)
        } catch (error) {
          reject(error)
        }
      }
      // 失败态,执行 onRejected,传入失败 reason
      if (this.state === REJECTED) {
        try {
          let x = onRejected(this.reason) // 传入 value
          reslove(x)
        } catch (error) {
          reject(error)
        }
      }
    })
    // 返回新的 promise 实例
    return promise2
  }

五、全部代码

// 声明 promise 三种状态
const PENDING = 'PENDING' // 等待态
const FULFILLED = 'FULFILLED' // 成功态
const REJECTED = 'REJECTED' // 失败态

class myPromise {
  // 通过 new 进行实例化时,传入 executor 执行器函数
  constructor(executor) {
    this.value = undefined // 成功的原因
    this.reason = undefined // 失败的原因
    this.state = PENDING // promise 状态,默认等待态
    this.onResolvedCallbacks = [] // 收集成功回调
    this.onRejectedCallbacks = [] // 收集失败回调
    // 成功 reslove 函数、失败reject函数,并传入executor
    const reslove = (value) => {
      // 等待态 --> 成功态
      if (this.state === PENDING) {
        this.value = value
        this.state = FULFILLED
        // 事件发布操作
        this.onResolvedCallbacks.forEach((fn) => fn())
      }
    }
    const reject = (reason) => {
      // 等待态 --> 失败态
      if (this.state === PENDING) {
        this.reason = reason
        this.state = REJECTED
        // 事件发布操作
        this.onRejectedCallbacks.forEach((fn) => fn())
      }
    }

    // 立即执行 executor 执行器函数,通过 try...catch... 进行异常捕捉;
    try {
      executor(reslove, reject)
    } catch (e) {
      reject(e) // 有异常,调用 reject 更新为失败态
    }
  }

  // 定义 then 方法:包含两个参数 onFulfilled 和 onRejected;
  // 根据 Promise 状态,执行 onFulfilled 或 onRejected;
  then(onFulfilled, onRejected) {
    let promise2 = new myPromise((reslove, reject) => {
      if (this.state === PENDING) {
        this.onResolvedCallbacks.push(() => {
          try {
            let x = onFulfilled(this.value) // 传入 value
            reslove(x)
          } catch (error) {
            reject(error)
          }
        })
        this.onRejectedCallbacks.push(() => {
          try {
            let x = onRejected(this.reason) // 传入 value
            reslove(x)
          } catch (error) {
            reject(error)
          }
        })
      }
      // 成功态,调用 onFulfilled,传入成功 value
      if (this.state === FULFILLED) {
        // 拿到回调处理的返回值
        try {
          let x = onFulfilled(this.value) // 传入 value
          reslove(x)
        } catch (error) {
          reject(error)
        }
      }
      // 失败态,执行 onRejected,传入失败 reason
      if (this.state === REJECTED) {
        try {
          let x = onRejected(this.reason) // 传入 value
          reslove(x)
        } catch (error) {
          reject(error)
        }
      }
    })
    // 返回新的 promise 实例
    return promise2
  }
}