手写 Promise 简版

107 阅读1分钟

Promises/A+ 规范传送门

  class Promise2 {
    #status = 'pending' // status 为私有属性,不能被外部篡改
    constructor(fn) {
      this.q = []  // 装填 f1/f2 的双元素队列,f1指成功时的函数,f2指失败时的函数
      const resolve = (data) => {
        this.#status = 'fulfilled'
        // 错误写法: this.q.map(f1f2 => { f1f2[0].call(undefined, data) }),因为如果第一个 then 的 f2 返回值不是 reject 的话,第二个 then 执行其 f1
        const f1f2 = this.q.shift() 
        if (!f1f2 || !f1f2[0]) return
        const x = f1f2[0].call(undefined, data)
        if (x instanceof Promise2) {
          x.then((data) => {
            resolve(data)
          }, (reason) => {
            reject(reason)
          })
        } else {
          resolve(x)
        }
      }
      const reject = (reason) => {
        this.#status = 'rejected'
        const f1f2 = this.q.shift()
        if (!f1f2 || !f1f2[1]) return
        const x = f1f2[1].call(undefined, reason)
        if (x instanceof Promise2) {
          x.then((data) => {
            resolve(data)
          }, (reason) => {
            reject(reason)
          })
        } else {
          resolve(x)
        }
      }
      fn.call(undefined, resolve, reject)
    }
    then(f1, f2) {
      this.q.push([f1, f2])
      // 如果出现 promise.then(s1,).then(s2, e2),则装填为 [[s, undifined], [s2, e2]]
    }
  }

// 使用
  const p = new Promise2(function (resolve, reject) {
    setTimeout(function () {
      reject('出错')
    }, 3000)
  })

  p.then((data) => { console.log(data) }, (r) => { console.error(r) })