Skip to content

Promise 相关方法实现

1. 实现符合 Promise/A+ 规范的Promise

代码实现
js
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  #state = PENDING
  #result = undefined
  #handlers = []

  constructor(executor) {
    const resolve = (value) => {
      this.#changeState(FULFILLED, value)
    }
    const reject = (reason) => {
      this.#changeState(REJECTED, reason)
    }
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }

  #changeState(state, val) {
    if (this.#state !== PENDING) return
    this.#state = state
    this.#result = val
    this.#run()
  }

  // 是否为Promise
  #isPromiseLike(value) {
    if (value !== null && (typeof value === 'object' || typeof value === 'function')) {
      return typeof value.then === 'function'
    }
    return false
  }

  // 执行函数放入微队列
  #runMicroTask(func) {
    // node 环境
    if (typeof process === 'object' && typeof process.nextTick === 'function') {
      process.nextTick(func)
    }
    // 浏览器环境
    else if (typeof MutationObserver === 'function') {
      const ob = new MutationObserver(func)
      const textNode = document.createTextNode('1')
      ob.observe(textNode, {
        characterData: true
      })
      textNode.data = '2'
    }
    // 其他环境
    else {
      setTimeout(func, 0)
    }
  }

  #runOne(callback, resolve, reject) {
    this.#runMicroTask(() => {
      if (typeof callback !== 'function') {
        const settled = this.#state === FULFILLED ? resolve : reject
        settled(this.#result)
        return
      }
      try {
        const x = callback(this.#result)
        if (this.#isPromiseLike(x)) {
          x.then(resolve, reject)
        } else {
          reject(x)
        }
      } catch (err) {
        reject(err)
      }
    })
  }

  #run() {
    if (this.#state === PENDING) return
    while (this.#handlers.length) {
      const { onFulfilled, onRejected, resolve, reject } = this.#handlers.shift()
      if (this.#state === FULFILLED) {
        this.#runOne(onFulfilled, resolve, reject)
      } else {
        this.#runOne(onRejected, resolve, reject)
      }
    }
  }

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this.#handlers.push({ onFulfilled, onRejected, resolve, reject })
      this.#run()
    })
  }
}

// 测试示例
const p1 = new MyPromise((resolve, reject) => {
  console.log('resolve')
  setTimeout(() => {
    resolve(123)
  }, 1000)
})
p1.then(
  (res) => {
    console.log('then 完成1', res)
    return new MyPromise((resolve, reject) => {
      reject(456)
    })
  },
  (err) => {
    console.log('catch 失败1', err)
  }
).then(
  (res) => {
    console.log('then 完成2', res)
  },
  (err) => {
    console.log('catch 失败2', err)
  }
)

基于 MIT 许可发布