手写一个符合 Promise/A+ 规范的 Promise

class MyPromise {
  constructor(executor) {
    this.state = 'pending'
    this.value = undefined
    this.reason = undefined
    this.onFulfilledCallbacks = []
    this.onRejectedCallbacks = []

    const resolve = (value) => {
      if (this.state !== 'pending') return
      if (value instanceof MyPromise) {
        value.then(resolve, reject)
        return
      }
      this.state = 'fulfilled'
      this.value = value
      this.onFulfilledCallbacks.forEach(fn => fn())
    }

    const reject = (reason) => {
      if (this.state !== 'pending') return
      this.state = 'rejected'
      this.reason = reason
      this.onRejectedCallbacks.forEach(fn => fn())
    }

    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }

  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
    onRejected = typeof onRejected === 'function' ? onRejected : e => { throw e }

    const promise2 = new MyPromise((resolve, reject) => {
      const fulfilledTask = () => {
        queueMicrotask(() => {
          try {
            const x = onFulfilled(this.value)
            this.resolvePromise(promise2, x, resolve, reject)
          } catch (err) {
            reject(err)
          }
        })
      }

      const rejectedTask = () => {
        queueMicrotask(() => {
          try {
            const x = onRejected(this.reason)
            this.resolvePromise(promise2, x, resolve, reject)
          } catch (err) {
            reject(err)
          }
        })
      }

      if (this.state === 'fulfilled') fulfilledTask()
      else if (this.state === 'rejected') rejectedTask()
      else {
        this.onFulfilledCallbacks.push(fulfilledTask)
        this.onRejectedCallbacks.push(rejectedTask)
      }
    })

    return promise2
  }

  resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
      return reject(new TypeError('Chaining cycle'))
    }
    if (x instanceof MyPromise) {
      x.then(resolve, reject)
    } else if (x !== null && typeof x === 'object' || typeof x === 'function') {
      let then
      try {
        then = x.then
      } catch (err) {
        return reject(err)
      }
      if (typeof then === 'function') {
        let called = false
        try {
          then.call(
            x,
            y => {
              if (called) return
              called = true
              this.resolvePromise(promise2, y, resolve, reject)
            },
            r => {
              if (called) return
              called = true
              reject(r)
            }
          )
        } catch (err) {
          if (called) return
          reject(err)
        }
      } else {
        resolve(x)
      }
    } else {
      resolve(x)
    }
  }

  catch(fn) { return this.then(null, fn) }

  finally(fn) {
    return this.then(
      v => MyPromise.resolve(fn()).then(() => v),
      r => MyPromise.resolve(fn()).then(() => { throw r })
    )
  }

  static resolve(value) {
    if (value instanceof MyPromise) return value
    return new MyPromise(resolve => resolve(value))
  }

  static reject(reason) {
    return new MyPromise((_, reject) => reject(reason))
  }

  static all(promises) {
    return new MyPromise((resolve, reject) => {
      const results = []
      let count = 0
      promises.forEach((p, i) => {
        MyPromise.resolve(p).then(v => {
          results[i] = v
          if (++count === promises.length) resolve(results)
        }, reject)
      })
    })
  }

  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach(p => MyPromise.resolve(p).then(resolve, reject))
    })
  }
}

同分类其他题目