Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promise关键步骤实现 #7

Open
54leibo opened this issue Nov 8, 2019 · 0 comments
Open

Promise关键步骤实现 #7

54leibo opened this issue Nov 8, 2019 · 0 comments

Comments

@54leibo
Copy link
Owner

54leibo commented Nov 8, 2019


const isFunction = val => typeof val === 'function'

const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'

class MyPromise {
  constructor(handle) {
    // 保存Promise的状态和值
    this._status = PENDING
    this._value = undefined

    // 保存单个Promise多次调用then的回调
    this._fulfilledQueues = []
    this._rejectedQueues = []

    try {
      handle(this._resolve.bind(this), this._reject.bind(this))
    } catch (e) {
      this._reject(e)
    }
  }
  _resolve(val) {
    if(this._status !== PENDING) return

    const run = () => {
      const runFulfilled = (value) => {
        let cb
        this._status = FULFILLED
        this._value = val
        // 依次执行成功队列回调
        while (cb = this._fulfilledQueues.shift()) {
          cb(value)
        }
      }
      const runRejected = (value) => {
        let cb
        this._status = REJECTED
        this._value = val
        // 依次执行失败队列回调
        while (cb = this._rejectedQueues.shift()) {
          cb(value)
        }
      }

      // 传入Promise则由传入Promise的结果决定_status和_value
      if(val instanceof MyPromise) {
        val.then(runFulfilled, runRejected)
        return
      }

      runFulfilled(val)
    }

    // 模拟Promise在本次事件循环末执行
    setTimeout(run, 0)
  }
  _reject(val) {
    if(this._status !== PENDING) return

    // 不同于_resolve,即时是传入Promise也直接作为值传递给回调
    const run = () => {
      this._status = REJECTED
      this._value = val
      let cb
      // 依次执行失败队列回调
      while (cb = this._rejectedQueues.shift()) {
        cb()
      }
    }
    // 模拟Promise在本次事件循环末执行
    setTimeout(run, 0)
  }
  then(onFulFilled, onRejected) {
    const { _status, _value } = this
    return new MyPromise((onFulFilledNext, onRejectedNext) => {
      const fulFilled = (val) => {
        try {
          // onFulFilled 不是函数
          if(!isFunction(onFulFilled)) {
            onFulFilledNext(val)
            return
          }

          // onFulFilled 返回了Promise,则该Promise决定了then返回Promise的状态
          const res = onFulFilled(val)
          if(res instanceof MyPromise) {
            res.then(onFulFilledNext, onRejectedNext)
            return
          }

          // onFulFilled 返回普通值
          onFulFilledNext(res)
        } catch (err) {
          // onFulFilled 内执行报错
          onRejectedNext(err)
        }
      }
      const rejected = (val) => {
        try {
          // onRejected 不是函数
          if(!isFunction(onFulFilled)) {
            onRejectedNext(val)
            return
          }

          // onRejected 返回了Promise,则该Promise决定了then返回Promise的状态
          const res = onRejected(val)
          if(res instanceof MyPromise) {
            res.then(onFulFilledNext, onRejectedNext)
            return
          }

          // onRejected 返回普通值
          onRejectedNext(res)
        } catch (err) {
          // onRejected 内执行报错
          onRejectedNext(err)
        }
      }

      switch (_status) {
        // 当状态为pending时,将then方法回调函数加入执行队列等待执行
        case PENDING:
          this._fulfilledQueues.push(fulFilled)
          this._rejectedQueues.push(rejected)
          break
        // 当前状态已改变是,立即执行回调函数
        case FULFILLED:
          fulFilled(_value)
          break
        case REJECTED:
          rejected(_value)
          break
      }
    })
  }
  catch(onRejected) {
    return this.then(undefined, onRejected)
  }
  finally(onFinally) {
    // onFinally 不是函数
    if(!isFunction(onFinally)) {
      onFinally = () => {}
    }

    // 返回Promise且保持原Promise结果,onFinally返回结果并不重要
    // 暂时不对onFinally中报错进行处理,根据浏览器原生Promise处理,
    // 如果finally回调函数中产生报错,则该错误会被返回
    return this.then(
      value => MyPromise.resolve(onFinally()).then(() => value),
      error => MyPromise.resolve(onFinally()).then(() => {throw error})
        )
  }
  static resolve(val) {
    // 如果是Promise则直接返回
    if(val instanceof MyPromise) return val

    // 其它值则返回一个返回该值的已完成Promise
    return new MyPromise(resolve => resolve(val))
  }
  static reject(val) {
    // 不同于resolve,reject返回一个rejected的Promise,并把值直接返回
    return new MyPromise((undefined, rejected) => rejected(val))
  }
  static all(list) {
    if((list instanceof Array)) return
    // 当全部为fulfilled或有一个为rejected时结束,返回一个Promise
    // 若全部为fulfilled,则值为promiseArr中promise返回结果的按次序排列的数组
    // 若有一个为rejected,则值为发生rejected的参数
    const results = []
    return MyPromise((resolve, reject) => {
      for(let [i, v] of list.entries()) {
        // 如果值不是Promise则构建一个
        this.resolve(v).then((val) => {
          results[i] = val
          if(results.length === list.length) {
            resolve(results)
          }
        }, err => reject(err))
      }
    })
  }
  static race(list) {
    // 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
    return new MyPromise((resolve, reject) => {
      for (let p of list) {
        this.resolve(p).then(res => {
          resolve(res)
        }, err => {
          reject(err)
        })
      }
    })
  }
}

引用(建议先看这篇文章,本实现只是增加了一些小改动)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant