Promise和then源码

279 阅读2分钟

Promise源码

/*
尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
*/

// 定义三个状态
const PENDING = 'PENDING'
const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'
function resolvePromise(x, promise2, resolve, reject) {
  //判断x === promise, 抛出类型错误
  if (x === promise2) {
    console.log('======')
    return reject(new TypeError('类型错误'))
  }
  // 允许状态改变一次
  let called = false

  try {
    //判断x是否包含then属性,thenable
    if (typeof x === 'object' && x !== null) {
      const then = x.then
      if (typeof then === 'function') {
        // console.log(typeof then)
        x.then(
          x,
          v => {
            if (called) return
            called = true
            resolvePromise(v, promise2, resolve, reject)
          },
          r => {
            if (called) return
            called = true
            reject(r)
          }
        )
      } else {
        if (called) return
        called = true
        resolve(x)
      }
    } else {
      if (called) return
      called = true
      resolve(x)
    }
  } catch (e) {
    if (called) return
    called = true
    reject(e)
  }
}
class Promise {
  constructor(exectuor) {
    try {
      //捕获执行器错误
      exectuor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e)
    }
  }

  status = PENDING
  value = null
  reason = null
  //存储失败和成功的回调
  onFullFilledCallbacks = []
  onRejectedCallbacks = []

  static all(args) {
    return new Promise((resolve, reject) => {
      args.reduce((prev, curr, i, arr) => {
        if (curr instanceof Promise) {
          curr.then(
            v => {
              prev[i] = v
              if (prev.length === arr.length) {
                resolve(prev)
              }
            },
            r => {
              reject(r)
            }
          )
        } else {
          prev[i] = curr
        }
        return prev
      }, [])
    })
  }
  static resolve(v) {
    if (v instanceof Promise) return v
    return new Promise((resolve, reject) => resolve(v))
  }
  static reject(r) {
    return new Promise((resolve, reject) => {
      reject(r)
    })
  }
  static allSettled(args) {
    return new Promise((resolve, reject) => {
      function addData(prev, index, value) {
        prev[index] = value
        if (prev.length === args.length) {
          resolve(prev)
        }
      }
      args.reduce((prev, curr, index, arr) => {
        if (curr instanceof Promise) {
          curr.then(
            res => {
              addData(prev, index, {
                value: res,
                status: 'fulfilled'
              })
            },
            r => {
              addData(prev, index, {
                reason: r,
                status: 'rejected'
              })
            }
          )
        } else {
          addData(prev, index, {
            reason: curr,
            status: 'fulfilled'
          })
        }
      })
    })
  }

  static race(args) {
    return new Promise((resolve, reject) => {
      args.forEach(item => {
        if (item instanceof Promise) {
          item.then(
            v => {
              resolve(v)
            },
            r => {
              reject(r)
            }
          )
        } else {
          resolve(item)
        }
      })
    })
  }

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

  resolve = v => {
    //只有状态为pending才执行
    if (this.status === PENDING) {
      this.status = RESOLVED
      this.value = v
      console.log(this.onFullFilledCallbacks)
      this.onFullFilledCallbacks.forEach(c => c())
    }
  }

  reject = r => {
    if (this.status === PENDING) {
      this.status = REJECTED
      this.reason = r
      this.onRejectedCallbacks.forEach(c => c())
    }
  }

  then(onFullFilled, onRejected) {
    debugger
    //onFullFilled onRejected类型判断
    if (typeof onFullFilled !== 'function') onFullFilled = v => v
    if (typeof onFullFilled !== 'function') {
      onRejected = r => {
        throw r
      }
    }
    const promise2 = new Promise((resolve, reject) => {
      if (this.status === RESOLVED) {
        // Promise为微任务,所以放到微任务队列执行
        queueMicrotask(() => {
          try {
            const x = onFullFilled(this.value)
            resolvePromise(x, promise2, resolve, reject)
          } catch (e) {
            reject(e)
          }
        })
      }

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

      if (this.status === PENDING) {
        //如果状态为pending,则执行方法放入数组中,等待resolve或reject时候执行
        this.onFullFilledCallbacks.push(() => {
          queueMicrotask(() => {
            try {
              const x = onFullFilled(this.value)
              resolvePromise(x, promise2, resolve, reject)
            } catch (e) {
              reject(e)
            }
          })
        })

        this.onRejectedCallbacks.push(() => {
          queueMicrotask(() => {
            try {
              const x = onRejected(this.reason)
              resolvePromise(x, promise2, resolve, reject)
            } catch (e) {
              reject(e)
            }
          })
        })
      }
    })
    return promise2
  }
}

Promise.deferred = function() {
  var result = {}
  result.promise = new Promise(function(resolve, reject) {
    result.resolve = resolve
    result.reject = reject
  })

  return result
}

module.exports = Promise

then源码

then(onFullFilled, onRejected) {
    if (typeof onFullFilled !== 'function') onFullFilled = v => v
    if (typeof onFullFilled !== 'function') {
      onRejected = r => {
        throw r
      }
    }
    const promise2 = new Promise((resolve, reject) => {
      if (this.status === RESOLVED) {
        // Promise为微任务,所以放到微任务队列执行
        queueMicrotask(() => {
          try {
            const x = onFullFilled(this.value)
            resolvePromise(x, promise2, resolve, reject)
          } catch (e) {
            reject(e)
          }
        })
      }

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

      if (this.status === PENDING) {
        //如果状态为pending,则执行方法放入数组中,等待resolve或reject时候执行
        this.onFullFilledCallbacks.push(() => {
          queueMicrotask(() => {
            try {
              const x = onFullFilled(this.value)
              resolvePromise(x, promise2, resolve, reject)
            } catch (e) {
              reject(e)
            }
          })
        })

        this.onRejectedCallbacks.push(() => {
          queueMicrotask(() => {
            try {
              const x = onRejected(this.reason)
              resolvePromise(x, promise2, resolve, reject)
            } catch (e) {
              reject(e)
            }
          })
        })
      }
    })
    return promise2
  }