手写Promise

58 阅读1分钟

MyPromise

class MyPromise {
  constructor(executor) {
    //初始状态
    this.state = "pending"
    //成功传递值
    this.value = null
    //拒绝原因
    this.reason = undefined
    //异步调用 resolve、reject 方法时先执行then,把后续执行函数先push到数组中
    this.onResolvedCallbacks = []
    this.onRejectCallbacks = []
    let resolve = (value) => {
      if (this.state === "pending") {
        this.state = "fulfilled"
        this.value = value
        //执行异步调用后的then传递函数
        this.onResolvedCallbacks.forEach((fn) => fn())
      }
    }
    let reject = (reason) => {
      if (this.state === "pending") {
        this.state = "rejected"
        this.reason = reason
        this.onRejectCallbacks.forEach((fn) => fn())
      }
    }
    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }
  then(onFulfilled, onRejected) {
    //判断传递的是否是一个函数
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (err) => {
            throw err
          }
    //后续return一个新的promise,实现链式调用
    let promise2 = new MyPromise((resolve, reject) => {
      //正常的 resolve
      if (this.state === "fulfilled") {
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value)
            //得到 返回值实现链式调用
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        })
      }
      if (this.state === "rejected") {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        })
      }
      //异步的 resolve、reject
      if (this.state === "pending") {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          })
        })
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          })
        })
      }
    })
    return promise2
  }
  catch = function (fn) {
    return this.then(null, fn)
  }
  //全部的promise成功才返回,只有有拒绝就返回拒绝状态
  static all (promises) {
    const values = []
    return new MyPromise((resolve, reject) => {
      promises.forEach((promise) => {
        promise.then(
          (value) => {
            values.push(value)
            if (values.length === promises.length) resolve(values)
          },
          (reason) => {
            reject(reason)
          }
        )
      })
    })
  }
  static race (promises) {
    return new MyPromise((resolve, reject) => {
      promises.map((promise) => {
        promise.then(
          (value) => resolve(value),
          (reason) => reject(reason)
        )
      })
    })
  }
  static resolve (val) {
    return new MyPromise((resolve, reject) => {
      reject(val)
    })
  }
  static reject (val) {
    return new MyPromise((resolve, reject) => {
      reject(val)
    })
  }
}
//限定promise的返回值
function resolvePromise(promise2, x, resolve, reject) {
  //返回值与本身一样就抛出错误
  if (x === promise2) {
    return reject(new TypeError("chaining cycl detected for promise"))
  }
  let called
  //不是空 是 对象 或者函数的情况
  if (x != null && (typeof x === "object" || typeof x === "function")) {
    try {
      let then = x.then
      //说明是一个promise则继续递归调用
      if (typeof then === "function") {
        then.call(
          x,
          (y) => {
            if (called) return
            called = true
            resolvePromise(x, y, resolve, reject)
          },
          (err) => {
            if (called) return
            called = true
            reject(err)
          }
        )
      //说明返回的是一个对象直接抛出
      } else {
        resolve(x)
      }
    } catch (e) {
      if (called) return
      called = true
      reject(e)
    }
  //说明返回的是一个普通值直接抛出
  } else {
    resolve(x)
  }
}