MyPromise

63 阅读3分钟

写写Promise

对promise的功能不描述

  Promise是构造函数,通过new关键字可以直接获取到实例,且实例可以链式调用then、catch、finally方法,且Promise 自身身上也有 resolve、reject、all、race等方法

/**
 * @param {*} executor 执行器函数,此函数有两个形参 resolve和reject
 */
function MyPromise(executor) {
  // 添加属性

  /** 默认状态 */
  this.PromiseState = 'pending'
  /** 默认结果值 */
  this.PromiseResult = null
  // // ???  因为需要在 MyPromise 中添加属性
  // 声明自身的属性
  this.callbacks = []

  /** 此处需要保存实例对象的 this 的值  */
  const _this = this

  /** 因为执行器函数中有两个形参,所以此处声明 myResolve 和 myReject */
  /** 因为在执行器函数中 调用的 resolve 函数都参数 所以此处需要补充 形参 data */
  function myResolve(data) {
    /** 因为promise存在状态凝固 所以 在promise的状态发生改变后 就不会再继续执行了 */
    if (_this.PromiseState !== 'pending') return
    /** 设置对象的状态 [[PromiseState]] */
    _this.PromiseState = 'fulfilled' // 或者 resolved
    /** 设置对象的结果值 [[PromiseResult]] */
    _this.PromiseResult = data

    // 异步任务情况下 遍历 .then方法中 保存在 MyPromise 中的 成功的方法
    setTimeout(() => {
      // 加上 setTimeout 进入 任务队列
      _this.callbacks.forEach((itemThen) => {
        itemThen.onResolved(data)
      })
    })
  }

  /** 因为在执行器函数中 调用的 reject 函数都参数 所以此处需要补充 形参 data */
  function myReject(data) {
    /** 因为promise存在状态凝固 所以 在promise的状态发生改变后 就不会再继续执行了 */
    if (_this.PromiseState !== 'pending') return
    /** 设置对象的状态 [[PromiseState]] */
    _this.PromiseState = 'rejected'
    /** 设置对象的结果值 [[PromiseResult]] */
    _this.PromiseResult = data

    // 异步任务情况下 遍历 .then方法中 保存在 MyPromise 中的 失败的方法

    setTimeout(() => {
      // 加上 setTimeout 进入 任务队列
      _this.callbacks.forEach((itemThen) => {
        itemThen.onRejected(_this.PromiseResult)
      })
    })
  }

  try {
    // !/** 执行器函数 是同步调用的 */
    executor(myResolve, myReject)
  } catch (error) {
    //  修改 MyPromise 对象状态为失败
    myReject(error)
  }
}

/**
 * then 中有两个参数,一个成功 一个失败
 * @param {*} onResolved
 * @param {*} onRejected
 */
MyPromise.prototype.then = function (onResolved, onRejected) {
  const _this = this

  // 处理异常穿透,在then 方法里,如果如果没有第二个方法,来处理异常,我们需要创建一个 reject,来抛出异常 直接赋值给第二个参数
  if (typeof onRejected !== 'function') {
    onRejected = (reason) => {
      throw reason
    }
  }

  // then()的值传递功能
  if (typeof onResolved !== 'function') {
    onResolved = (value) => value
  }

  return new MyPromise((resolve, reject) => {
    function _callback(cb) {
      try {
        /** .then 中的resolve中的实参,是通过此处获取到的实例上的实参this.PromiseResult传下去的 */
        // 获取 .then 方法中的 resolve 的 Promise结果
        const result = cb(_this.PromiseResult)
        // 判断result 是否在 MyPromise 的实例上
        if (result instanceof MyPromise) {
          // 如果在,则根据 MyPromise的then方法中的 Promise对象 的结果进行返回 成功则成功 失败则失败
          result.then(
            (v) => {
              resolve(v)
            },
            (r) => {
              reject(r)
            }
          )
        } else {
          // 如果不在,直接返回 成功的 result
          resolve(result)
        }
      } catch (e) {
        // 对抛出的异常 直接reject 出去
        reject(e)
      }
    }

    /** 通过实例对象的上的状态判断,到底该调用哪个函数 */
    if (this.PromiseState === 'fulfilled') {
      // 加上 setTimeout 进入 任务队列
      setTimeout(() => {
        _callback(onResolved)
      })
    }

    /** 通过实例对象的上的状态判断,到底该调用哪个函数 */
    if (this.PromiseState === 'rejected') {
      // 加上 setTimeout 进入 任务队列
      setTimeout(() => {
        _callback(onRejected)
      })
    }

    if (this.PromiseState === 'pending') {
      // 在此处 把 onResolved/onRejected 保存在 MyPromise callback中
      this.callbacks.push({
        onResolved: function () {
          _callback(onResolved)
        },
        onRejected: function () {
          _callback(onRejected)
        },
      })
    }
  })
}

/**
 * catch 中只有一个参数,失败的方法
 * @param {*} onRejected
 */
MyPromise.prototype.catch = function (onRejected) {
  return this.then(undefined, onRejected)
}

MyPromise.resolve = function (value) {
  return new MyPromise((resolve, reject) => {
    if (value instanceof MyPromise) {
      value.then(
        (v) => {
          resolve(v)
        },
        (r) => {
          reject(r)
        }
      )
    } else {
      resolve(value)
    }
  })
}

MyPromise.reject = function (reason) {
  return new MyPromise((resolve, reject) => {
    reject(reason)
  })
}

MyPromise.all = function (promises) {
  return new MyPromise((resolve, reject) => {
    let count = 0
    const arr = []
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(
        (v) => {
          count++
          arr[i] = v

          if (count === promises.length) {
            resolve(arr)
          }
        },
        (r) => {
          reject(r)
        }
      )
    }
  })
}

MyPromise.race = function (promises) {
  return new MyPromise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(
        (v) => {
          resolve(v)
        },
        (r) => {
          reject(r)
        }
      )
    }
  })
}



在线测试