手写promise

142 阅读1分钟
function Promise2(cb) {
  this.state = 'pedding'
  this.value
  this.reason
  this.fulfilledFns = []
  this.rejectedFns = []
  const resolve = (val) => {
    if (this.state === 'pedding') {
      this.value = val
      this.state = 'fulfilled'
      setTimeout(() => {
        this.fulfilledFns.forEach(fn => {
          fn(this.value)
        })
    }
  }
  const reject = (val) => {
    if (this.state === 'pedding') {
      this.state = 'rejected'
      this.reason = val
      setTimeout(() => {
        this.rejectedFns.forEach(fn => {
          fn(this.reason)
        })
      })

    }
  }
  try {
    cb(resolve, reject)
  } catch (e) {
    reject(e)
  }
}
Promise2.prototype.then = function (resolveFn, rejectFn) {
  resolveFn = typeof resolveFn === 'function' ? resolveFn : () => { }
  rejectFn = typeof rejectFn === 'function' ? rejectFn : () => { }

  let promise2

  switch (this.state) {
    case 'pedding':
      promise2 = new Promise2((resolve, reject) => {
        // this.fulfilledFns.push(() => { resolve(resolveFn(this.value)) })
        这里应该使用resolve的,,因为下一层的then 从resolveFn 开始
        // this.rejectedFns.push(() => { resolve(rejectFn(this.reason)) })
        this.fulfilledFns.push(() => {resolvePromise(promise2, resolveFn(this.value), resolve, reject) })
        this.rejectedFns.push(() => { resolvePromise(promise2, rejectFn(this.reason), resolve, reject) })
      })
      break;
    case 'fulfilled':
      promise2 = new Promise2((resolve, reject) => {
        try {
          // resolve(resolveFn(this.value))
          resolvePromise(promise2, rejectedFns(this.value), resolve, reject)
        } catch (e) {
          reject(e);//error catch
        }
      })
      break;
    case 'rejected':
      promise2 = new Promise2((resolve, reject) => {
        try {
          // resolve(rejectFn(this.reason))
          这里应该使用resolve的,因为下一层的then 从resolveFn 开始
          // reject(rejectFn(this.reason))
          resolvePromise(promise2, rejectedFns(this.reason), resolve, reject)
        } catch (e) {
          reject(e);//error catch
        }
      })
      // console.log(JSON.stringify(promise2,null,2))
      break;


  }

  return promise2

}
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise'))
  }
  let called
  if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
    try {
      let then = x.then
      // 默认为promise
      if (typeof then === 'function') {
        then.call(x, y => {
          if (called) {
            return
          }
          called = true
          resolvePromise(promise2, y, resolve, reject)
        }, err => {
          if (called) {
            return
          }
          called = true
          reject(err)
        })
      } else {
        resolve(x)
      }
    } catch (err) {
      if (called) {
        return
      }
      called = true
      reject(err);
    }
  } else {
    resolve(x)
  }
}