手写promise原理

/**
 * promise 原理
 * 
 * 1. exector
 *    需要传递一个执行函数exector参数,用于执行何时进行状态改变的逻辑
 *    这个函数需要两个参数 resovle, reject 分别用于处理成功、失败的状态改变
 * 
 * 2. status
 *    status 状态
 *    仅可以通过内部的resolve、reject内置函数进行修改,且仅当status == 'pending'状态可以被修改,状态一旦确定就无法被再次修改
 *    resolve、reject都会接收一个参数,并分别保存在data和reason中
 * 
 * 3. then 方法
 *    then 方法主要用于监听成功或者失败的回调
 *    接收两个参数resovleHandle、和rejectHandle函数用于处理成功、失败时的回调
 *    每个then函数仅会执行其中一个函数 成功或者失败,主要由status来判断
 *    且resovleHandle、和rejectHandle会自动传入内部保存的对应的数据data和reason
 *    若执行器内的状态改变涉及异步操作时,then方法实际处于pending的状态
 *    异步处理
 *        此时我们如果希望在特定的时刻执行then方法传递的resovleHandle、和rejectHandle,我们则需要对他们进行缓存,并在希望调用的时候调用(resolve, reject)
 *        cache: {resolveHandle: [], rejectHandle: []},由于可能会有多个then方法的监听,所以这两个cache是数组
 * 
 * 4. then 方法的链式调用
 *    1. 链式调用的核心是then方法返回一个新的promise,并将then方法内的主要逻辑放在新promise的exector内执行,这是为了后面的一个步骤做准备
 *    2. 新的promise的then会接收上一个promise的then方法resolveHandle和rejectHandle返回的值
 *    3. 处理then方法未传递回调函数的防错机制
 *    4. 仅当上一个promise函数或者then内部逻辑发生错误的时候会触发下一个then方法的reject回调
 *    5. 若then的回调返回的是一个VPromise实例,我们需要立刻执行该promise的then方法,并在对应的回调中调用我们新的promise的状态函数
 *    6. 内部代码执行错误捕获机制,为then方法和exector函数内进行try/catch机制来捕获错误
 * 
 */

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

class VPromise {
  constructor(exector) {
    // promise状态
    this.status = PENDING
    // 成功数据
    this.data = undefined
    // 失败原因
    this.reason = undefined
    // 回调缓存3
    this.cache = {
      resovleHandle: [],
      rejectHandle: []
    }
    // 执行执行器
    try {
      exector(this.resolve, this.reject)
    } catch (error) {
      this.reject(error.message || error)
    }
  }

  // 成功时执行操作
  resolve = (v) => {
    let {
      status,
      cache
    } = this
    // 判断status状态
    if (status !== PENDING) return
    // 修改状态为成功
    this.status = FULFILLED
    // 存储成功
    this.data = v

    // 执行特殊的异步回调
    if (cache && cache.resovleHandle) {
      while (cache.resovleHandle.length > 0) {
        let handle = cache.resovleHandle.pop()
        handle && handle(this.data)
      }
    }
  }

  // 失败时执行操作
  reject = (v) => {
    let {
      status, cache
    } = this
    // 判断status状态
    if (status !== PENDING) return
    // 修改状态为失败
    this.status = REJECTED
    // 存储失败原因
    this.reason = v
    // 执行特殊的异步回调
    if (cache && cache.rejectHandle) {
      while (cache.rejectHandle.length > 0) {
        let handle = cache.rejectHandle.pop()
        handle && handle(this.reason)
      }
    }
  }

  // 设置回调缓存
  setCache(res, rej) {
    res && this.cache.resovleHandle.push(res)
    rej && this.cache.rejectHandle.push(rej)
  }

  // then方法监听成功或失败操作
  then(resovleHandle = v => v, rejectHandle = e => {
    throw e
  }) {
    let promise = new VPromise((res, rej) => {
      // then方法主要运行逻辑
      if (this.status === FULFILLED) {
        let value = resovleHandle(this.data)
        // 为了将value传递给then方法的回调,我们可以传递给res,间接传递给then
        // 执行res,不仅可以传递参数,还可以开启下一个promis的执行
        // res(value)
        asyncHandle(value, res, rej)
      } else if (this.status === REJECTED) {
        // console.log('error: ' + this.reason)
        let error = rejectHandle(this.reason)
        // 同上
        asyncHandle(error, res, rej)
      } else {
        // 异步有点不同
        this.setCache((data) => {
          try {
            let value = resovleHandle(data)
            asyncHandle(value, res, rej)
          } catch (error) {
            rej(error.message || error)
          }
        }, (reason) => {
          try {
            let error = rejectHandle(reason)
            asyncHandle(error, res, rej)
          } catch (error) {
            rej(error.message || error)
          }
        })
      }
    })
    return promise
  }

  // 并行操作all
  static all(arrary = []) {
    let result = []
    let count = 0
    return new VPromise((resolve, reject) => {
      function addData(key, value) {
        result[key] = value
        count++
        if (count === arrary.length) {
          resolve(result)
        }
      }
      for (let i = 0; i < arrary.length; i++) {
        let res = arrary[i]
        if (res instanceof VPromise) {
          // 是promise
          res.then(value => addData(i, value), reason => reject(reason))
        } else {
          // 普通值
          addData(i, res)
        }
      }
    })
  }
  // finally 方法,不管promise的状态是什么都会执行finally传递的函数,并且可以链式调用
  finally(fn) {
    // 若fn的返回值是promise,需要等待该promise执行完成在向下执行
    return this.then((data) => {
      return VPromise.resolve(fn()).then(() => data)
    }, (reason) => {
      return VPromise.resolve(fn()).then(() => {
        throw reason
      }, () => {
        throw reason
      })
    })
  }

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

  // resolve方法,返回一个新的状态为resolve方法
  static resolve(data) {
    // 判断是否是promise对象
    // 是直接返回
    if (data instanceof VPromise) return data
    // 否则返回一个状态为fulfilled的promise对象
    return new VPromise((resolve) => resolve(data))
  }

  // reject方法,返回一个新的状态为reject方法
  static reject(data) {
    // 判断是否是promise对象
    // 是直接返回
    if (data instanceof VPromise) return data
    // 否则返回一个状态为rejected的promise对象
    return new VPromise((resolve, reject) => reject(data))
  }


}

// 用于处理promise和非promise的情况
function asyncHandle(value, res, rej) {
  if (value instanceof VPromise) {
    // 说明是promise
    // 执行promise的then方法来判断何是执行res或reject
    // 并将then方法回调中的传入值作为下一个promise的参数值
    value.then((data) => {
      res(data)
    }, (err) => {
      rej(err)
    })
  } else {
    // 否则是普通值
    res(value)
  }
}

let promise = new VPromise((res, rej) => {
  // res(1)
  // rej('c023-error')
  // a()
  setTimeout(() => {
    // res('success')
    rej('fail...')
  }, 1000)
})

注:本文章仅用于学习与总结,如有疑问欢迎交流

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值