带你了解 “老生常谈”的Promise的实现(四)

61 阅读3分钟

一、基础功能描述

错误处理

  • executor中的错误
  • then 第一个成功回调中的错误
  • then 第二个失败回调中的错误
  • 异步中的错误处理

二、代码实现

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class MPromise {
  constructor(executor){
    try{
      executor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e)
    }
  }
  status = PENDING

  // 成功后的值
  value = undefined
  //失败后的原因
  reason = undefined

  // 为了支持异步修改状态
  // 成功回调
  successCallback = []
  // 失败回调
  failCallback = []


  // resolve 和 reject都是箭头函数。
  // 因为在使用的过程中,直接调用,this指向的是window或者undefined,要让它指向MPromise的实例对象,所以此时应该 使用箭头函数
  resolve = (value) => { // value成功后的值
    // 状态一旦修改后不能再更改
    if(this.status != PENDING) return
    this.status = FULFILLED
    this.value = value

    // 异步:判断成功回调是否存在,如果存在调用
    // this.successCallback && this.successCallback(this.value)
    while(this.successCallback.length) this.successCallback.shift()()
  }

  reject = (reason) => { // reason失败后的原因
    // 状态一旦修改后不能再更改
    if(this.status != PENDING) return
    this.status = REJECTED
    this.reason = reason

    // 异步:判断失败回调是否存在,如果存在调用
    // this.failCallback && this.failCallback(this.reason)
    while(this.failCallback.length) this.failCallback.shift()()
  }

  then(successCallback, failCallback) {
    let promise2 = new MPromise((resolve, reject) => {
      // 状态判断
      // 同步: 一次或者多次都直接执行
      if(this.status == FULFILLED) {
        setTimeout(()=>{ // 如果不用setTimeout,此时获取不到promise2
          try {
            // then 方法的返回值x,是一个普通值
            let x = successCallback(this.value)
            // 如果是一个普通值,直接调用resolve
            // 如果是一个promise对象,查看promise对象的返回结果,根据返回的结果,决定是调用resolve还是reject
            resolvePromise(promise2, x, resolve, reject) // 如果不用setTimeout,此时获取不到promise2
          } catch (e) {
            reject(e)
          }
        })
      } else if(this.status == REJECTED){
        // 同步: 一次或者多次都直接执行
        setTimeout(()=>{ // 如果不用setTimeout,此时获取不到promise2
          try {
            // then 方法的返回值x,是一个普通值
            let x = failCallback(this.reason)
            // 如果是一个普通值,直接调用resolve
            // 如果是一个promise对象,查看promise对象的返回结果,根据返回的结果,决定是调用resolve还是reject
            resolvePromise(promise2, x, resolve, reject) // 如果不用setTimeout,此时获取不到promise2
          } catch (e) {
            reject(e)
          }
        })
      } else {
        // 此时说明 状态修改是异步的,需要将成功失败的回调存储起来
        // this.successCallback.push(successCallback)
        // this.failCallback.push(failCallback)
        // 返回值和错误处理
        this.successCallback.push(() => {
          setTimeout(()=>{ // 如果不用setTimeout,此时获取不到promise2
            try {
              // then 方法的返回值x,是一个普通值
              let x = successCallback(this.value)
              // 如果是一个普通值,直接调用resolve
              // 如果是一个promise对象,查看promise对象的返回结果,根据返回的结果,决定是调用resolve还是reject
              resolvePromise(promise2, x, resolve, reject) // 如果不用setTimeout,此时获取不到promise2
            } catch (e) {
              reject(e)
            }
          })
        })
        this.failCallback.push(() => {
          setTimeout(()=>{ // 如果不用setTimeout,此时获取不到promise2
            try {
              // then 方法的返回值x,是一个普通值
              let x = failCallback(this.reason)
              // 如果是一个普通值,直接调用resolve
              // 如果是一个promise对象,查看promise对象的返回结果,根据返回的结果,决定是调用resolve还是reject
              resolvePromise(promise2, x, resolve, reject) // 如果不用setTimeout,此时获取不到promise2
            } catch (e) {
              reject(e)
            }
          })
        })
      }
    });
    return promise2
  }
}
`

function resolvePromise(promise2, x, resolve, reject){
  // 判断 返回的promise 是否等于 then方法本身的promise,如果等于直接报错
  if(promise2 == x) {
    return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))
  }
  if(x instanceof MPromise) {
    // 返回的是promise
    // x.then(value=> resolve(value), reason => reject(reason)) 等价于
    x.then(resolve, reject)
  } else {
    // 普通值
    resolve(x)
  }
}
let pro = new MPromise((res, rej)=>{
  // throw new Error('executor error')
  // res('成功的值')
  rej('失败原因')
})

// pro.then(value=> {
//   throw new Error('then error')
//   return 100
// }, (reason) => {
//   console.log(reason)
// })
// .then(value=> {
//   console.log(value)
// }, (reason) => {
//   console.log(reason, "then")
// })

pro.then(value=> {
  // throw new Error('then error')
  return 100
}, (reason) => {
  throw new Error('then error')
  console.log(reason)
  return 100
})
.then(value=> {
  console.log(value)
}, (reason) => {
  console.log(reason, "then")
})

恭喜你,终于学完啦