前端手写(四)——手写promise系列

x33g5p2x  于2022-03-28 转载在 其他  
字(2.9k)|赞(0)|评价(0)|浏览(333)

一、写在前面
之前就已经手写过promise,本次手写就是为了加强记忆。
二、手写源码

// 定义三个常量
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_PENDDING = 'pendding'
const PROMISE_STATUS_REJECTED = 'rejected'

function execFunc(func, value, resolve, reject) {
  try {
    let res = func(value)
    resolve(res)
  } catch (err) {
    reject(err)
  }
}

class MyPromise {
  constructor(exacutor) {
    this.status = PROMISE_STATUS_PENDDING
    this.reason = undefined
    this.value = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDDING) return
          this.value = value
          this.status = PROMISE_STATUS_FULFILLED
          this.onFulfilledFns.forEach(fn => fn(this.value))
        })
      }
    }

    const reject = (reason) => {
      if (this.status === PROMISE_STATUS_PENDDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDDING) return
          this.reason = reason
          this.status = PROMISE_STATUS_REJECTED
          this.onRejectedFns.forEach(fn => fn(this.reason))
        })
      }
    }

    exacutor(resolve, reject)
  }
  then(onFulfilled, onRejected) {
    onRejected = onRejected || (err => {
      throw err
    })
    return new MyPromise((resolve, reject) => {

      if (this.status === PROMISE_STATUS_FULFILLED) {
        if (onFulfilled) execFunc(onFulfilled, this.value, resolve, reject)
      }

      if (this.status === PROMISE_STATUS_REJECTED) {
        if (onRejected) execFunc(onRejected, this.reason, resolve, reject)
      }

      if (this.status === PROMISE_STATUS_PENDDING) {
        if (onFulfilled) this.onFulfilledFns.push(() => {
          execFunc(onFulfilled, this.value, resolve, reject)
        })
        if (onRejected) this.onRejectedFns.push(() => {
          execFunc(onRejected, this.reason, resolve, reject)
        })
      }
    })
  }

  // catch方法
  catch (onRejected) {
    return this.then(undefined, onRejected)
  }
  // finally方法
  finnally(onFinial) {
    this.then(() => {
      onFinial()
    }, () => {
      onFinial()
    })
  }

  // 实现MyPromise.resolve()方法
  static resolve(value) {
    return new MyPromise((resolve, reject) => {
      resolve(value)
    })
  }

  // 实现MyPromise.reject()方法
  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason)
    })
  }

  // 实现MyPromise.all()方法
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      let arr = []
      promises.forEach(item => {
        item.then(res => {
          arr.push(res)
          if (arr.length === promises.length) {
            resolve(arr)
          }
        }, err => {
          reject(err)
        })
      })
    })
  }

  // 实现MyPromise.allSettle()
  static allsettle(promises) {
    return new MyPromise((resolve, reject) => {
      let arr = []
      promises.forEach(item => {
        item.then(res => {
          arr.push({
            value: res,
            status: PROMISE_STATUS_FULFILLED
          })
          if(arr.length === promises.length) {
            resolve(arr)
          }
        }, err => {
          arr.push({
            value: err,
            status: PROMISE_STATUS_REJECTED
          })
          if(arr.length === promises.length) {
            resolve(arr)
          }
        })
      })
    })
  }

  // 实现MyPromise.race()方法
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach(item => {
        item.then(res => {
          resolve(res)
        }, err => {
          reject(err)
        })
      })
    })
  }

  // 实现MyPromise.any()方法
  static any(promises) {
    return new MyPromise((resolve, reject) => {
      let arr = []
      promises.forEach(item => {
        item.then(res => {
          resolve(res)
        }, err => {
          arr.push(err)
          if(arr.length === promises.length) {
            reject(new AggregateError(arr))
          }
        })
      })
    })
  }
}

相关文章