手写 promise


const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    try {
      executor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e)
    }
  }

  // promise 状态
  status = PENDING

  // 成功之后的值
  value = undefined

  // 失败之后的原因
  reason = undefined

  // 成功回调
  successCallback = []

  // 失败回调
  failCallback = []

  resolve = value => {
    // 如果 promise 状态不是等待,阻止程序向下执行
    if (this.status !== PENDING) return

    // 将 promise 状态更改为成功
    this.status = FULFILLED

    // 保存成功之后的值
    this.value = value

    // 如果成功回调队列里存在回调函数,调用队首回调函数
    while (this.successCallback.length) {
      this.successCallback.shift()()
    }
  }

  reject = reason => {
    // 如果 promise 状态不是等待,阻止程序向下执行
    if (this.status !== PENDING) return

    // 将 promise 状态更改为失败
    this.status = REJECTED

    // 保存失败之后的原因
    this.reason = reason

    // 如果失败回调队列里存在回调函数,调用队首回调函数
    while (this.failCallback.length) {
      this.failCallback.shift()()
    }
  }

  then(successCallback, failCallback) {
    // 如果then没有携带参数时,返回一个带参函数作为 successCallback 和 failCallback,向下传递
    successCallback = successCallback ? successCallback : value => value
    failCallback = failCallback ? failCallback : reason => { throw reason }
    let promise = new MyPromise((resolve, reject) => {
      // 判断状态
      if (this.status === FULFILLED) {
        setTimeout(() => {
          try {
            let result = successCallback(this.value)

            // 判断 result 的值是 普通值 还是 promise 对象
            // 如果是普通值,直接调用 resovle
            // 如果是 promise 对象,查看 promise 对象返回的结果
            // 再根据 promise 对象返回的结果,决定调用 resolve, 还是调用 reject
            resolvePromise(promise, result, resolve, reject)
          } catch (e) {
            reject(e)
          }
        }, 0)
      } else if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            let result = failCallback(this.reason)

            // 判断 result 的值是 普通值 还是 promise 对象
            // 如果是普通值,直接调用 resovle
            // 如果是 promise 对象,查看 promise 对象返回的结果
            // 再根据 promise 对象返回的结果,决定调用 resolve, 还是调用 reject
            resolvePromise(promise, result, resolve, reject)
          } catch (e) {
            reject(e)
          }
        }, 0)
      } else {
        // 等待状态
        // 将成功回调和失败回调存储起来
        this.successCallback.push(() => {
          setTimeout(() => {
            try {
              let result = successCallback(this.value)

              // 判断 result 的值是 普通值 还是 promise 对象
              // 如果是普通值,直接调用 resovle
              // 如果是 promise 对象,查看 promise 对象返回的结果
              // 再根据 promise 对象返回的结果,决定调用 resolve, 还是调用 reject
              resolvePromise(promise, result, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
        this.failCallback.push(() => {
          setTimeout(() => {
            try {
              let result = failCallback(this.reason)

              // 判断 result 的值是 普通值 还是 promise 对象
              // 如果是普通值,直接调用 resovle
              // 如果是 promise 对象,查看 promise 对象返回的结果
              // 再根据 promise 对象返回的结果,决定调用 resolve, 还是调用 reject
              resolvePromise(promise, result, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
      }
    })

    return promise

  }

  finally(callback) {
    // 获取当前 promise 对象的状态
    // 无论当前状态是成功还是失败,都调用 回调函数,并将结果传递下去
    return this.then(value => {
      // 调用静态方法 resolve ,处理 回调函数 返回的是 普通值 和 promise对象 这2种情况
      return MyPromise.resolve(callback()).then(() => value)
    }, reason => {
      return MyPromise.resolve(callback()).then(() => {throw reason})
    })
  }

  catch(failCallback) {
    return this.then(undefined, failCallback)
  }

  static all(array) {
    let result = []
    let index = 0

    return new MyPromise((resolve, reject) => {
      // 将完成的任务结果对应下标保存进 结果数组 中
      function addData(key, value) {
        result[key] = value
        // 当 index 和 array 数组长度一致时,说明数组内所有项都已执行完
        index++
        if (index === array.length) {
          resolve(result)
        }
      }

      // 遍历形参array,
      for(let i = 0; i < array.length; i++) {
        let current = array[i]

        // 判断数组当前项是 普通值 还是 promise 对象
        if (current instanceof MyPromise) {
          // 如果是 promise 对象,获取 promise 执行结果
          // promise 执行成功,对应数组下标保存进 结果数组 中
          // promise 执行失败,调用 reject
          current.then(value => addData(i, value), reason => reject(reason))
        } else {
          // 如果是 普通值,直接放入 结果数组中
          addData(i, current)
        }
      }
    })
  }

  static resolve(value) {
    // 判断传入参数是 普通值 还是 promise对象
    if (value instanceof MyPromise) return value

    return new MyPromise(resolve => resolve(value))
  }
}

function resolvePromise(promise, result, resolve, reject) {
  if (promise === result) {
    return reject(new TypeError('promise 循环调用'))
  }

  if (result instanceof MyPromise) {
    // promise 对象
    // result.then(value => resolve(value), reason => reject(reason))
    result.then(resolve, reject)
  } else {
    // 普通值
    resolve(result)
  }

}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值