promise

94 阅读2分钟
// promise 源码
class MyPromise {
  // 几个私有属性
  value = undefined
  successPool = []
  failPool = []
  status = 'pedding'

  constructor(fn) {
    try { fn(this.resolve, this.reject) }
    catch(e) { this.reject(e) }
  }

  resolve(value) {
    // 执行通过then塞入的回调函数
    const executeSuccessPool = () => {
      let cb 
      while (cb = this.successPool.shift()) {
        cb(this.value)
      }
    }

    // 执行通过then塞入的回调函数(失败)
    const executeFailPool = () => {
      let cb 
      while (cb = this.failPool.shift()) {
        cb(this.value)
      }
    }

    // 先看一下 传入的value是不是promise
    if(value instanceof MyPromise) {
      value.then(
        // 如果成功,就执行成功的回调
        v => {
          this.status = 'success'
          this.value = v
          executeSuccessPool()
        },
        // 如果失败,就执行失败的回调
        err => {
          this.status = 'fail'
          this.value = err
          executeFailPool()
        }
      )
    } else {
      this.value = value
      this.status = 'success'
      executeSuccessPool()
    }
  }


  reject(err) {
    // 一般err也不需要什么异步传递了,直接抛出错误即可
    this.status = 'fail'
    this.value = err

    executeFailPool()
  }


  catch(c) {
    this.then(undefined, c)
  }

  then(scb, fcb) {
    return new MyPromise((rel, rej) => {

      const resolveCb = () => {
        // 先判断用户使用的时候,是否传递了scb,如果没有直接传递当前链式调用的promise
        if (!scb || typeof scb !== 'function') {
          rel(this.value)
        } else {
          // 先执行回调函数
          const val = scb(this.value)
          // 判断val是不是还是promise
          if (val instanceof MyPromise) {
            val.then(rel, rej) // 传递状态
          } else {
            rel(val)
          }
        }
      }
      const rejectCb = () => {
        // 先判断用户使用的时候,是否传递了fcb,如果没有直接传递当前链式调用的promise
        if (!fcb || typeof fcb !== 'function') {
          rej(this.value)
        } else {
          // 先执行回调函数
          const val = fcb(this.value)
          // 判断val是不是还是promise
          if (val instanceof MyPromise) {
            val.then(rel, rej) // 传递状态
          } else {
            // 记住 这里是传递的rel 而不是你理解的对应的rej
            rel(val)
          }
        }
      }

      if (this.status === 'success') {
        // 直接执行成功回调 scb 并传递链式调用的promise的状态
        resolveCb()
      }

      if (this.status === 'fail') {
        rejectCb()
      }


      if (this.status === 'pedding') {
        // 塞入回调
        this.successPool.push(resolveCb)
        this.failPool.push(rejectCb)
      }
    })
  }

  _resolve(v) {
    if (v instanceof MyPromise) return v 
    return new MyPromise(rel => rel(v))
  }


  static all(arr) {
    const res = []
    let count = 0
    return new MyPromise((rel, rej) => {
      arr.forEach((i, index) => {
        this._resolve(i).then(
          v => {
            res[index] = v
            count++
            if (count === arr.length) rel(res)
          },
          // 如果有错误直接跳出
          err => {
            rej(err)
          }
        )
      })
    })
  }
  // all 的实现也给了我们启发,因为在错误之后就直接跳出了,它并不会传递catch, 所以说
  // 我们应该如何传递promise.all的错误
  // const wrapperPromise = p =>
  // p
  // .then(res => ({ res, err: null }))
  // .catch(err => ({ err, res: null }))
  // 这就让你的promise如果错误也能接受catch 然后再能then出去,参考如上reject的实现,能往下传递 then


  static race(arr) {
    return new MyPromise((rel, rej) => {
      for (const p of arr) {
        this._resolve(p).then(
          v => {
            rel(v)
          },
          err => {
            rej(err)
          }
        )
      }
    })
  }
}