手写promise

106 阅读3分钟

今天先实现了简洁版的promise

class Promise1 {
      static PENDING = "Pending"
      static FULFILLED = "Fulfilled"
      static REJECTED = "Rejected"
      constructor(executor) {
        this.initValue()
        this.initBind()
        try {
          executor(this.resolve, this.reject)
        } catch (e) {
          this.reject(e)
        }
      }
      // 绑定this值
      initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
      }
      // 初始化值
      initValue() {
        this.value = null // 终值
        this.reason = null // 拒因
        this.state = Promise1.PENDING // 状态
        this.onFulfilledCallback = [] // 成功回调
        this.onRejectedCallback = [] // 失败回调
      }
      resolve(value) {
        this.value = value
        this.state = Promise1.FULFILLED
        this.onFulfilledCallback.forEach(fn => fn(this.value))
      }
      reject(reason) {
        this.reason = reason
        this.state = Promise1.REJECTED
        this.onRejectedCallback.forEach(fn => fn(this.reason))
      }
      then(onFulfilled, onRejected) {
        /**
         * 因为这样会有才能穿透,如果不是函数不能直接忽略
         * .then()
         * .then(val => {
         *    console.log('value',val) // value 1
         * })
         * 
         * */
        if (typeof onFulfilled !== 'function') {
          onFulfilled = function (value) {
            return value
          }
        }
        if (typeof onFulfilled !== 'function') {
          onRejected = function (reason) {
            return reason
          }
        }
        if (this.state === Promise1.FULFILLED) {
          setTimeout(() => {
            onFulfilled(this.value)
          })
        }
        if (this.state === Promise1.REJECTED) {
          setTimeout(() => {
            onRejected(this.reason)
          })
        }
        if (this.state === Promise1.PENDING) {
          this.onFulfilledCallback.push(value => {
            setTimeout(() => {
              onFulfilled(value)
            })
          })
          this.onRejectedCallback.push(reason => {
            setTimeout(() => {
              onRejected(reason)
            })
          })
        }
      }
    }







    console.log(111)
    const promise1 = new Promise1((resolve, rejected) => {
      // throw new Error('hahah')
      setTimeout(() => {
        resolve(222)
      })
      // rejected(2)
    })
    promise1.then(result => {
      console.log(result, 'result')
    }, reason => {
      console.log(reason, 'reason')
    })
    console.log(333)

明天继续后面的实现

3.19补充

class Promise1 {
  static PENDING = "Pending"
  static FULFILLED = "Fulfilled"
  static REJECTED = "Rejected"
  static resolvePromise = function (promise2, x, resolve, reject) {
    // 循环调用的时候会出现相等的情况
    /**
     * const p1 = new Promise(resolve => {
          resolve(1)
        })
        const p2 = p1.then(() => {
          return p2
        })
    */
    if (promise2 === x) {
      try {
        throw new TypeError("Chaining cycle detected for promise")
      } catch (e) {
        reject(e)
      }
    }

    // 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
    let called = false
    if (x instanceof Promise1) {
      x.then(value => {
        Promise1.resolvePromise(x, value, resolve, reject)
      }, (reason) => {
        reject(reason)
      })
    } else if (typeof x !== null && (typeof x === 'object' || typeof x === 'function')) {
      try {
        const then = x.then
        if (typeof then === 'function') {
          // 如果then 由 Object.defineProperty get处理了再返回的,如果处理时出现了错误,则有会抛出异常
          then.call(x, value => {
            if (called) return
            called = true
            Promise1.resolvePromise(x, value, resolve, reject)
          }, reason => {
            if (called) return
            called = true
            reject(reason)
          })
        } else {
          if (called) return
          called = true
          resolve(x)
        }
      } catch (reason) {
        if (called) return
        called = true
        reject(reason)
      }
    } else {
      resolve(x)
    }
  }
  constructor(executor) {
    this.initValue()
    this.initBind()
    try {
      executor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e)
    }
  }
  // 绑定this值
  initBind() {
    this.resolve = this.resolve.bind(this)
    this.reject = this.reject.bind(this)
  }
  // 初始化值
  initValue() {
    this.value = null // 终值
    this.reason = null // 拒因
    this.state = Promise1.PENDING // 状态
    this.onFulfilledCallback = [] // 成功回调
    this.onRejectedCallback = [] // 失败回调
  }
  resolve(value) {
    this.value = value
    this.state = Promise1.FULFILLED
    this.onFulfilledCallback.forEach(fn => fn(this.value))
  }
  reject(reason) {
    this.reason = reason
    this.state = Promise1.REJECTED
    this.onRejectedCallback.forEach(fn => fn(this.reason))
  }
  then(onFulfilled, onRejected) {
    /**
     * 因为这样会有才能穿透,如果不是函数不能直接忽略
     * .then()
     * .then(val => {
     *    console.log('value',val) // value 1
     * })
     * 
     * */
    if (typeof onFulfilled !== 'function') {
      onFulfilled = function (value) {
        return value
      }
    }
    if (typeof onFulfilled !== 'function') {
      onRejected = function (reason) {
        return reason
      }
    }
    // 实现链式调用
    // then 方法必须返回一个 promise 对象 注3
    //promise2 = promise1.then(onFulfilled, onRejected);
    let promise2 = new Promise1((resolve, reject) => {
      if (this.state === Promise1.FULFILLED) {
        setTimeout(() => {
          try {
            /**
            如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)
            如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e
            如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
            如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因
            */
            const x = onFulfilled(this.value)
            Promise1.resolvePromise(promise2, x, resolve, reject)
            // resolve(x)
          } catch (e) {
            reject(e)
          }

        })
      }
      if (this.state === Promise1.REJECTED) {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason)
            Promise1.resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }

        })
      }
      if (this.state === Promise1.PENDING) {
        this.onFulfilledCallback.push(value => {
          setTimeout(() => {
            try {
              const x = onFulfilled(value)
              Promise1.resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }

          })
        })
        this.onRejectedCallback.push(reason => {
          setTimeout(() => {
            try {
              const x = onRejected(reason)
              Promise1.resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }

          })
        })
      }
    })
    return promise2
  }
}

const p1 = new Promise1(resolve => {
  resolve(1)
})
p1
  .then(value => {
    return new Promise1(resolve => {
      resolve(new Promise1(resolve => {
        resolve(333)
      }))
    })
  })
  .then(value => {
    console.log('value', value)
  })

如果想要检测自己写的promise是否符合promise A+ 的规范,那么可以按照下面的方式去检测 先全局安装

  npm i promises-aplus-tests -g

然后在你写的promise文件最后面写上这段代码


Promise1.defer = Promise1.deferred = function () {
  let dfd = {}
  dfd.promise = new Promise1((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
}
module.exports = Promise1;

最后运行这段就可以检测了,然后根据报错去修改你的promise吧

    npx promises-aplus-tests 你的promise文件

参考: 文章 -> Promise A+ 规范【中文版】

视频 -> b站:手摸手教你实现Promise/A+规范