简单手写实现promise


(function (window) {
  const PENDING = 'pending'   // 初始化未确定状态
  const RESOLVED = 'resolved' // 成功的状态
  const REJECTED = 'rejected' // 失败的状态
  
  function Promise(actuator) {
    
    // 当前Promise实例
    const self = this
    // 初始化实例的状态: pending  resolved  rejected
    self.status = PENDING
    // 存储数据, 初始为undefined
    self.data = undefined
    // 存储promise对象的回调函数
    self.callbacks = []

    /* 
      改变promise状态,指定成功的value
    */
    function resolve(value) {
      /* 
        promise的状态的改变只能改变一次
      */
      // 判断当前promise状态, 只有pending状态调用resolve才会生效
      if (self.status !== PENDING) return

      // 改变promise的状态
      self.status = RESOLVED
      // 存储成功的数据
      self.data = value

      // 异步调用所有缓存待执行成功的回调函数
      if (self.callbacks.length > 0) { // 缓存的回调函数的数组里面有回调函数
        // 异步执行,指定成功的回调函数
        setTimeout(() => {
          self.callbacks.forEach(callbacksObj=>{ // 遍历callbacks
            callbacksObj.onResolved(self.data) // 执行成功的回调, 并将成功的数据传递给指定成功的回调
          }) 
        });
      }
    }
    /* 
      改变promise状态,指定失败的reason
    */
    function reject(reason) {

      /* 
        promise的状态的改变只能改变一次
      */
      // 判断当前promise状态, 只有pending状态调用reject才会生效
      if (self.status !== PENDING) return

      // 改变promise的状态
      self.status = REJECTED
      // 存储失败的数据
      self.data = reason

      // 异步调用所有缓存待执行失败的回调函数
      if (self.callbacks.length > 0) { // 缓存的回调函数的数组里面有回调函数
        // 异步执行,指定失败的回调函数
        /* 
          真正的promise不是使用的setTimeout,因为promise的异步任务是微队列的任务,使用setTimeout模拟
        */
        setTimeout(() => {
          self.callbacks.forEach(callbacksObj=>{ // 遍历callbacks
            callbacksObj.onRejected(self.data) // 执行失败的回调, 并将失败的数据传递给指定失败的回调
          }) 
        });
      }
    }

    // 捕获执行器异常
    try { 
      // 调用执行器函数来启动异步任务
      actuator(resolve, reject)
    } catch (error) {
      // 执行器出现异常,调用reject,改变promise状态 pending ==> rejected
      reject(error)
    }

  }

  /* 
    用来指定成功或失败的回调函数
    1) 如果当前的promise是resolved状态, 异步执行成功的回调函数onResolved
    2) 如果当前的promise是rejected状态, 异步执行成功的回调函数onRejected
    3) 如果当前的promise是pending状态, 保存回调函数
    返回一个新的promise对象------(返回的新的promise的状态,是由onResolved或onRejected执行的结果决定)
    2.1) (onResolved或onRejected)抛出error          ==> 新promise的状态变为rejected, 结果值为error
    2.2) (onResolved或onRejected)返回值不是promise  ==> 新promise的状态变为resolved, 结果值为(onResolved或onRejected)返回值
    2.3) (onResolved或onRejected)返回值是promise    ==> (onResolved或onRejected)返回的promise的结果决定then返回的promise的状态

  */
  Promise.prototype.then = function (onResolved, onRejected) {

    // 保存调用then方法的promise对象
    const self = this
    
    // 如果没有指定失败的回调函数,将失败的值向下传递
    onRejected = typeof onRejected === 'function' ? onRejected : (reason) => {throw reason}
    // 如果没有指定成功的回调函数,将成功的值向下传递
    onResolved = typeof onResolved === 'function' ? onResolved : value => value


    // 返回一个promise对象
    return new Promise((resolve,reject)=>{

      // 调用成功或失败的回调函数, 根据执行的结果改变then方法返回的promise的状态
      function handle(callback) {
        try {
          const result = callback(self.data)
          if (result instanceof Promise) { // 2.3) (onResolved或onRejected)返回值是promise
            result.then( // 通过result这个promise成功或失败的结果来决定then方法返回的promise的状态
              value => resolve(value),
              reason => reject(reason)
            )
            // 上面三行代码的简写
            // result.then(resolve, reject)
          }else{ // 2.2) (onResolved或onRejected)返回值不是promise
            resolve(result)
          }
        } catch (error) {
          // 2.1) (onResolved或onRejected)抛出error
          reject(error)
        }
      }

      // 1)
      if (self.status === RESOLVED) { // 调用then方法的promise对象的状态为resolved, 
        //异步执行成功的回调函数onResolved
        setTimeout(() => {
          /* 
            try {
              // 接收onResolved成功的回调的返回值, 来决定then方法返回的promise的状态
              const result = onResolved(self.data)
              if (result instanceof Promise) { // 2.3) (onResolved或onRejected)返回值是promise
                result.then( // 通过result这个promise成功或失败的结果来决定then方法返回的promise的状态
                  value => resolve(value),
                  reason => reject(reason)
                )
                // 上面三行代码的简写
                // result.then(resolve, reject)
              }else{ // 2.2) (onResolved或onRejected)返回值不是promise
                resolve(result)
              }
            } catch (error) {
              // 2.1) (onResolved或onRejected)抛出error
              reject(error)
            } 
          */
          handle(onResolved)
        });
      // 2)
      }else if (self.status === REJECTED) { // 调用then方法的promise对象的状态为rejected, 
        // 异步执行成功的回调函数onRejected
        setTimeout(() => {
          /* 
            try {
              const result = onRejected(self.data)
              if (result instanceof Promise) { // 2.3) (onResolved或onRejected)返回值是promise
                result.then((resolve,reject)=>{ // 通过result这个promise成功或失败的结果来决定then方法返回的promise的状态
                  value => resolve(value),
                  reason => reject(reason)
                })
                // result.then(resolve, reject)
              }else{
                // 2.2) (onResolved或onRejected)返回值不是promise
                resolve(result)
              }
            } catch (error) {
              // 2.1) (onResolved或onRejected)抛出error
              reject(error)
            }  
          */
          handle(onRejected)
        });
      // 3)
      } else{ // 调用then方法的promise对象的状态为pending, 保存回调函数
        /* // 保存回调函数 ---> 当前promise对象里面
        // callbacks里面的回调函数是由执行resolve或reject方法调用的
        this.callbacks.push({ // 将2个回调函数以对象的显示保存到promise实例上
          onResolved,
          onRejected
        }) */  // 使用此方法保存成功或失败的回调函数,在resolve或reject执行的时候,去执行这2个函数,没办法修改then方法返回的新的promise的状态
        this.callbacks.push({ // 不直接保存失败或成功的回到函数, 保存的是包含回调函数调用的函数
          onResolved (value){ //注意: 调用callbacks里面的成功或是失败的回调都是在resolve函数或reject函数里面执行的,所以这里不许要异步执行成功或失败的回调函数
            // onResolved(value)
            /* 
              try {
                // 接收onResolved成功的回调的返回值, 来决定then方法返回的promise的状态
                const result = onResolved(self.data)
                if (result instanceof Promise) { // 2.3) (onResolved或onRejected)返回值是promise
                  result.then( // 通过result这个promise成功或失败的结果来决定then方法返回的promise的状态
                    value => resolve(value),
                    reason => reject(reason)
                  )
                  // 上面三行代码的简写
                  // result.then(resolve, reject)
                }else{ // 2.2) (onResolved或onRejected)返回值不是promise
                  resolve(result)
                }
              } catch (error) {
                // 2.1) (onResolved或onRejected)抛出error
                reject(error)
              } 
            */
            handle(onResolved)
          },
          onRejected (reason){ // 此处的参数可以不用接收
            // onRejected(reason)
            /* 
              try {
                const result = onRejected(self.data)
                if (result instanceof Promise) { // 2.3) (onResolved或onRejected)返回值是promise
                  result.then((resolve,reject)=>{ // 通过result这个promise成功或失败的结果来决定then方法返回的promise的状态
                    value => resolve(value),
                    reason => reject(reason)
                  })
                  // result.then(resolve, reject)
                }else{
                  // 2.2) (onResolved或onRejected)返回值不是promise
                  resolve(result)
                }
              } catch (error) {
                // 2.1) (onResolved或onRejected)抛出error
                reject(error)
              } 
            */
            handle(onRejected)
          }
        })
      }
    })


  }

  /* 
    用来指定失败回调函数的方法
    catch是then的语法糖
  */
  Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected)
  }
  /* 
    返回一个promise对象(返回的promise对象,可能是失败的可能是成功的)
    value可能是一个一般的值, 也可能是一个promise对象
  */
  Promise.resolve = function (value) {
    return new Promise((resolve,reject)=>{
      if (value instanceof Promise) {
        value.then(resolve, reject)
      }else{
        resolve(value)
      }
    })
  }
  /* 
    返回一个失败状态的promise对象
  */
  Promise.reject = function (reason) {
    return new Promise((resolve,reject)=>{
      reject(reason)
    })
  }
  
  Promise.all = function (promises) {
    return new Promise((resolve, reject)=>{
      // 遍历所有promise, 取所有的结果
      let results = new Array(promises.length) // 保存成功的promise数据的数组
      let resultCount = 0 // 已经成功的promise数量
      promises.forEach((p, index)=>{
        p.then(
          value => {
            resultCount++
            results[index] = value
            if (resultCount === promises.length) {
              resolve(results)
            }
          },
          reason => {reject(reason)}
        )
      })
    })
  }
  /* 
    返回一个promise对象, 此promise对象的状态是由传入的promise数组第一个返回的promise决定的
  */
  Promise.race = function (promises) {
    return new Promise((resolve, reject)=>{
      // 遍历所有promise, 取所有的结果
      promises.forEach(p=>{
        // race返回的promise由第一个返回的promise来决定其race返回的promise的状态
        p.then(resolve, reject)
      })
    })
  }

  // 对外暴露
  window.Promise = Promise


})(window)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值